fix: remove API key from plain-text config file, add workflow permissions
- config.py: stop writing API_KEY to .immich_config.json; direct users to .env instead. Resolves CodeQL py/clear-text-storage-sensitive-data. - test.yml, lint.yml: add permissions: contents: read to satisfy actions/missing-workflow-permissions scanner. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,8 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
env:
|
env:
|
||||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|||||||
+7
-5
@@ -67,12 +67,11 @@ class _Config:
|
|||||||
self.ENABLE_CACHE = os.getenv("ENABLE_CACHE", "false").lower() in ("true", "1", "yes")
|
self.ENABLE_CACHE = os.getenv("ENABLE_CACHE", "false").lower() in ("true", "1", "yes")
|
||||||
self.CACHE_DIR = os.getenv("CACHE_DIR", ".if_cache")
|
self.CACHE_DIR = os.getenv("CACHE_DIR", ".if_cache")
|
||||||
|
|
||||||
# Fall back to config file for missing values
|
# Fall back to config file for non-sensitive values (API_KEY not stored here)
|
||||||
if CONFIG_FILE.exists():
|
if CONFIG_FILE.exists():
|
||||||
try:
|
try:
|
||||||
data = json.loads(CONFIG_FILE.read_text())
|
data = json.loads(CONFIG_FILE.read_text())
|
||||||
self.IMMICH_URL = self.IMMICH_URL or data.get("IMMICH_URL")
|
self.IMMICH_URL = self.IMMICH_URL or data.get("IMMICH_URL")
|
||||||
self.API_KEY = self.API_KEY or data.get("API_KEY")
|
|
||||||
if not os.getenv("OUTPUT_DIR"):
|
if not os.getenv("OUTPUT_DIR"):
|
||||||
self.OUTPUT_DIR = data.get("OUTPUT_DIR", self.OUTPUT_DIR)
|
self.OUTPUT_DIR = data.get("OUTPUT_DIR", self.OUTPUT_DIR)
|
||||||
except (json.JSONDecodeError, OSError) as e:
|
except (json.JSONDecodeError, OSError) as e:
|
||||||
@@ -84,13 +83,16 @@ class _Config:
|
|||||||
cls._instance = None
|
cls._instance = None
|
||||||
|
|
||||||
def save(self) -> None:
|
def save(self) -> None:
|
||||||
"""Persist configuration to file."""
|
"""Persist non-sensitive configuration to file.
|
||||||
|
|
||||||
|
API_KEY is intentionally excluded — store it in .env or as an
|
||||||
|
environment variable instead of a plain-text config file.
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
CONFIG_FILE.write_text(
|
CONFIG_FILE.write_text(
|
||||||
json.dumps(
|
json.dumps(
|
||||||
{
|
{
|
||||||
"IMMICH_URL": self.IMMICH_URL,
|
"IMMICH_URL": self.IMMICH_URL,
|
||||||
"API_KEY": self.API_KEY,
|
|
||||||
"OUTPUT_DIR": self.OUTPUT_DIR,
|
"OUTPUT_DIR": self.OUTPUT_DIR,
|
||||||
},
|
},
|
||||||
indent=2,
|
indent=2,
|
||||||
@@ -113,8 +115,8 @@ class _Config:
|
|||||||
|
|
||||||
if not self.API_KEY:
|
if not self.API_KEY:
|
||||||
console.print("[yellow]Immich API Key not found.[/yellow]")
|
console.print("[yellow]Immich API Key not found.[/yellow]")
|
||||||
|
console.print("[dim]Tip: set API_KEY in your .env file to avoid re-entering it.[/dim]")
|
||||||
self.API_KEY = Prompt.ask("Enter Immich API Key", password=True)
|
self.API_KEY = Prompt.ask("Enter Immich API Key", password=True)
|
||||||
self.save()
|
|
||||||
|
|
||||||
def validate(self) -> None:
|
def validate(self) -> None:
|
||||||
"""Raise ValueError if required config is missing."""
|
"""Raise ValueError if required config is missing."""
|
||||||
|
|||||||
Reference in New Issue
Block a user