v0.5.12 : la cle Crawl4AI quitte config.env pour un fichier dedie (0600)

Une cle en clair dans config.env finit dans les copier-coller de depannage.
Elle vit desormais dans $JEAN_HOME/.crawl4ai_key en 0600, comme la cle de
completion (.api_key) ; les installations qui l'avaient dans config.env sont
migrees a la premiere lecture, et l'ecriture efface toute trace residuelle.

Approche proposee par @feanor91 dans la PR #15 — merci a lui.
This commit is contained in:
nathaninline committed 2026-07-28 11:43:40 +02:00
1 parent 8956b1ed76
commit 15bb9358bc
8 files changed
+45 -11

No files matched your search

Binary file not shown.
Binary file not shown.
+3 -3
View File
@@ -3,13 +3,13 @@
"FileVersion": {
"Major": 0,
"Minor": 5,
"Patch": 11,
"Patch": 12,
"Build": 0
},
"ProductVersion": {
"Major": 0,
"Minor": 5,
"Patch": 11,
"Patch": 12,
"Build": 0
},
"FileFlagsMask": "3f",
@@ -25,7 +25,7 @@
"LegalCopyright": "Copyright (c) 2026 AJEAN contributors. MIT License.",
"OriginalFilename": "jean.exe",
"ProductName": "AJEAN",
"ProductVersion": "0.5.11",
"ProductVersion": "0.5.12",
"Comments": "https://github.com/nathaninline/jean — projet open source (MIT)"
},
"VarFileInfo": {
+1 -1
View File
@@ -201,7 +201,7 @@ func safePresetPath(name string) (string, error) {
// paramètres de modèle) qui doivent survivre à un changement de preset. Sans ça,
// écraser config.env avec le preset ré-imposerait le mode mémoire et effacerait
// l'URL du serveur internet à chaque bascule — ce qui obligeait à tout remettre.
var preservedKeys = []string{"MEM_MODE", "CRAWL4AI_URL", "CRAWL4AI_KEY"}
var preservedKeys = []string{"MEM_MODE", "CRAWL4AI_URL"}
// SwitchToPreset backs up the current config and copies the target into place,
// then restarts the service. Les réglages « appareil » (preservedKeys) sont
+37 -4
View File
@@ -40,10 +40,43 @@ func crawl4aiURL() string {
return strings.TrimRight(u, "/")
}
// crawl4aiKey renvoie la clé d'accès au serveur Crawl4AI (config.env
// CRAWL4AI_KEY), vide si le serveur est ouvert. Envoyée en « Authorization:
// Bearer … », ce qu'attend Crawl4AI quand l'authentification est activée.
func crawl4aiKey() string { return strings.TrimSpace(ReadConfig()["CRAWL4AI_KEY"]) }
// crawl4aiKey renvoie la clé d'accès au serveur Crawl4AI, vide si le serveur
// est ouvert. Envoyée en « Authorization: Bearer … », ce qu'attend Crawl4AI
// quand l'authentification est activée (CRAWL4AI_API_TOKEN côté serveur).
//
// Elle vit dans $JEAN_HOME/.crawl4ai_key (0600) et NON dans config.env : ce
// dernier est le fichier qu'on copie-colle pour demander de l'aide, une clé en
// clair dedans finit par fuiter. Même modèle que la clé de complétion
// (.api_key). Les installations qui l'avaient dans config.env sont migrées à
// la première lecture.
func crawl4aiKey() string {
if b, err := os.ReadFile(crawlKeyPath()); err == nil {
if k := strings.TrimSpace(string(b)); k != "" {
return k
}
}
// Migration depuis l'ancien emplacement (jean 0.5.11).
if k := strings.TrimSpace(ReadConfig()["CRAWL4AI_KEY"]); k != "" {
if err := writeCrawlKey(k); err == nil {
_ = SetConfigKey("CRAWL4AI_KEY", "")
}
return k
}
return ""
}
// writeCrawlKey enregistre (clé non vide) ou efface (clé vide) la clé Crawl4AI.
func writeCrawlKey(key string) error {
_ = SetConfigKey("CRAWL4AI_KEY", "") // ne laisse rien traîner dans config.env
if key == "" {
if err := os.Remove(crawlKeyPath()); err != nil && !os.IsNotExist(err) {
return err
}
return nil
}
_ = os.MkdirAll(JeanHome(), 0o755)
return os.WriteFile(crawlKeyPath(), []byte(key+"\n"), 0o600)
}
// crawlAuth pose l'en-tête d'authentification sur une requête vers Crawl4AI.
// Sans clé configurée, la requête part telle quelle.
+1 -1
View File
@@ -289,7 +289,7 @@ func cmdInternet(args []string) error {
return fmt.Errorf("usage: jean internet key <clé> (vide pour l'enlever : jean internet key \"\")")
}
k := strings.TrimSpace(args[1])
if err := SetConfigKey("CRAWL4AI_KEY", k); err != nil {
if err := writeCrawlKey(k); err != nil {
return err
}
reachMu.Lock()
+2 -1
View File
@@ -10,7 +10,7 @@ import (
"strings"
)
const Version = "0.5.11"
const Version = "0.5.12"
// Main est le vrai main() du binaire (cmd/jean ne fait que l'appeler).
func Main() {
@@ -220,6 +220,7 @@ func mcpConfigPath() string { return filepath.Join(JeanHome(), "mcp.json") }
func legacySkillsFlag() string { return filepath.Join(skillsDir(), ".enabled") }
func legacyToolsFlag() string { return filepath.Join(JeanHome(), ".tools_enabled") }
func apiKeyPath() string { return filepath.Join(JeanHome(), ".api_key") }
func crawlKeyPath() string { return filepath.Join(JeanHome(), ".crawl4ai_key") }
func serviceName() string {
if n := os.Getenv("JEAN_SERVICE"); n != "" {
return n
+1 -1
View File
@@ -585,7 +585,7 @@ func handleInternet(w http.ResponseWriter, r *http.Request) {
_ = json.NewDecoder(r.Body).Decode(&req)
// Clé d'accès au serveur Crawl4AI : chaîne vide = on l'enlève.
if req.Key != nil {
if err := SetConfigKey("CRAWL4AI_KEY", strings.TrimSpace(*req.Key)); err != nil {
if err := writeCrawlKey(strings.TrimSpace(*req.Key)); err != nil {
sendJSON(w, 500, map[string]any{"ok": false, "error": err.Error()})
return
}