diff --git a/README.md b/README.md
index 52e9458..c3a213a 100644
--- a/README.md
+++ b/README.md
@@ -60,6 +60,7 @@ Use only the files that fit the project. For a tiny script repo, `AGENTS.md`, `R
| `files/AGENTS.md` | `AGENTS.md` |
| `files/project.md` | `.codex/project.md` |
| `files/build-gitea.yml` | `.gitea/workflows/build.yml` |
+| `files/security-scan-gitea.yml` | `.gitea/workflows/security-scan.yml` |
| `files/release-checklist.md` | `docs/release-checklist.md` |
| `files/security-review.md` | `docs/security-review.md` |
| `files/blueprint.md` | `blueprint.md` |
@@ -123,6 +124,7 @@ When applying this kit, an agent should:
- keep `AGENTS.md` and `.codex/project.md` aligned,
- update `README.md` whenever README blueprint files change,
- update security and release docs when release behavior changes,
+- add or preserve scheduled security automation for releasable projects,
- update `docs/agent-handoff.md` when work is interrupted, risky, or multi-session,
- run `git diff --check` before finishing,
- run the cheapest reliable verification command,
@@ -130,6 +132,21 @@ When applying this kit, an agent should:

+## Scheduled Security Automation
+
+`files/security-scan-gitea.yml` provides an optional weekly Gitea workflow for releasable projects.
+
+It checks:
+
+- stack-specific dependency vulnerabilities,
+- suspicious code patterns,
+- committed secrets or local config files,
+- AI instruction-injection indicators.
+
+The workflow is intentionally conservative. If it fails, an agent should inspect the matches and decide whether they are real risks, documentation examples, or test fixtures. Do not silence the workflow without documenting why.
+
+
+
## Gitea API Token
When working with private repositories on `git.wilkensxl.de`, Codex agents may find a local `GITEA_TOKEN` environment variable on the machine.
diff --git a/agent-quickstart.md b/agent-quickstart.md
index 0e34ed1..7edbb9d 100644
--- a/agent-quickstart.md
+++ b/agent-quickstart.md
@@ -9,6 +9,7 @@ Read manifest.json first.
Use its copyMap for file destinations.
Use new-repository.md or existing-project.md as the task workflow.
Use matching profiles/*.md guidance after detecting the stack.
+For releasable projects, add or preserve scheduled security automation.
Check git status before editing.
Preserve unrelated user changes.
Replace all applicable placeholders and remove non-applicable placeholder sections.
@@ -74,6 +75,10 @@ Does the project have CI?
yes -> patch existing workflow
no -> add .gitea/workflows/build.yml only when commands are known
+Is the project releasable or does it process user/secrets/config data?
+ yes -> add .gitea/workflows/security-scan.yml or preserve equivalent scheduled security automation
+ no -> document why scheduled security automation is not needed
+
Are commands unknown?
yes -> document PENDING in .codex/project.md
no -> wire commands into AGENTS.md and CI
@@ -123,6 +128,7 @@ docs/release-checklist.md
docs/security-review.md
docs/agent-handoff.md
.gitea/workflows/build.yml
+.gitea/workflows/security-scan.yml
```
For README-generator projects:
diff --git a/existing-project.md b/existing-project.md
index 913dacf..04b3bab 100644
--- a/existing-project.md
+++ b/existing-project.md
@@ -120,6 +120,8 @@ If CI does not exist:
- remove stack-specific steps that do not apply,
- keep publishing disabled until credentials and artifact names are known.
+For releasable projects, add `.gitea/workflows/security-scan.yml` unless the repository already has equivalent scheduled security automation. If an existing scanner is present, document it in `.codex/project.md` instead of duplicating it.
+
### 6. Security Review
Fill `docs/security-review.md` with known facts.
diff --git a/files/AGENTS.md b/files/AGENTS.md
index 659194a..c0f462c 100644
--- a/files/AGENTS.md
+++ b/files/AGENTS.md
@@ -20,6 +20,7 @@ PROJECT_NAME: PROJECT_DESCRIPTION
- After pushing commits that trigger a Gitea workflow, poll the workflow run until it succeeds. If it fails or is cancelled, inspect the failing job/logs, fix the issue when in scope, push again, and repeat the workflow check loop. Fixing and pushing a workflow failure is not a stopping point.
- When the project uses `blueprint.md` and `blueprint.json` for README generation, keep the rainbow `{{ template:section-line }}` divider between major README sections. Do not replace it with plain `---` unless the target renderer cannot display inline images.
- If README blueprint files are changed, regenerate or update `README.md` in the same change and verify the generated output renders reasonably.
+- For releasable projects, add or preserve `.gitea/workflows/security-scan.yml` using `files/security-scan-gitea.yml` unless the repository already has equivalent scheduled security automation.
## Commands
@@ -54,6 +55,7 @@ ARTIFACT_NAME
- Review `docs/security-review.md` before release work.
- Fill `docs/security-review.md` with actual checked commands and results when performing release-readiness work.
+- Review scheduled security workflow failures before changing code. Treat matches as leads: they may be true positives, documentation examples, or test fixtures.
- Treat generated credentials and config files as sensitive.
- Keep external network calls documented.
- Prefer local processing for user data.
diff --git a/files/security-scan-gitea.yml b/files/security-scan-gitea.yml
new file mode 100644
index 0000000..d514dcc
--- /dev/null
+++ b/files/security-scan-gitea.yml
@@ -0,0 +1,174 @@
+name: Scheduled Security Scan
+
+on:
+ schedule:
+ - cron: "17 3 * * 1"
+ workflow_dispatch:
+
+jobs:
+ security-scan:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Detect project stack
+ id: detect
+ shell: bash
+ run: |
+ stacks=""
+
+ [ -f package.json ] && stacks="${stacks} node"
+ { [ -f pyproject.toml ] || [ -f requirements.txt ]; } && stacks="${stacks} python"
+ [ -f Cargo.toml ] && stacks="${stacks} rust"
+ [ -f go.mod ] && stacks="${stacks} go"
+ { [ -f Dockerfile ] || [ -f compose.yml ] || [ -f docker-compose.yml ]; } && stacks="${stacks} docker"
+
+ echo "stacks=${stacks:-generic}" >> "$GITHUB_OUTPUT"
+ echo "Detected stacks:${stacks:- generic}"
+
+ - name: Node production dependency audit
+ if: contains(steps.detect.outputs.stacks, 'node')
+ run: npm audit --omit=dev --audit-level=high
+
+ - name: Python dependency audit
+ if: contains(steps.detect.outputs.stacks, 'python')
+ shell: bash
+ run: |
+ python -m pip install --upgrade pip pip-audit
+ if [ -f requirements.txt ]; then
+ pip-audit -r requirements.txt
+ else
+ pip-audit
+ fi
+
+ - name: Rust dependency audit
+ if: contains(steps.detect.outputs.stacks, 'rust')
+ shell: bash
+ run: |
+ cargo install cargo-audit --locked
+ cargo audit
+
+ - name: Go vulnerability scan
+ if: contains(steps.detect.outputs.stacks, 'go')
+ shell: bash
+ run: |
+ go install golang.org/x/vuln/cmd/govulncheck@latest
+ govulncheck ./...
+
+ - name: Suspicious code pattern scan
+ shell: bash
+ run: |
+ grep_excludes=(
+ --exclude-dir=.git
+ --exclude-dir=node_modules
+ --exclude-dir=dist
+ --exclude-dir=build
+ --exclude-dir=release
+ --exclude=security-scan.yml
+ )
+
+ patterns=(
+ 'eval\s*\('
+ 'new Function\s*\('
+ 'dangerouslySetInnerHTML'
+ 'innerHTML\s*='
+ 'child_process'
+ 'exec\s*\('
+ 'spawn\s*\('
+ 'shell\.openExternal'
+ 'nodeIntegration:\s*true'
+ 'webSecurity:\s*false'
+ 'allowRunningInsecureContent:\s*true'
+ 'curl .*sh'
+ 'wget .*sh'
+ )
+
+ found=0
+ for pattern in "${patterns[@]}"; do
+ if grep -RInE "${grep_excludes[@]}" "$pattern" .; then
+ found=1
+ fi
+ done
+
+ if [ "$found" -eq 1 ]; then
+ echo "Suspicious code patterns were found. Review the matches above."
+ exit 1
+ fi
+
+ - name: Secret and config leak scan
+ shell: bash
+ run: |
+ grep_excludes=(
+ --exclude-dir=.git
+ --exclude-dir=node_modules
+ --exclude-dir=dist
+ --exclude-dir=build
+ --exclude-dir=release
+ --exclude=security-scan.yml
+ )
+
+ patterns=(
+ 'BEGIN (RSA |EC |OPENSSH |)PRIVATE KEY'
+ 'AKIA[0-9A-Z]{16}'
+ 'xox[baprs]-[0-9A-Za-z-]+'
+ 'gh[pousr]_[0-9A-Za-z_]+'
+ 'sk-[A-Za-z0-9]{20,}'
+ 'api[_-]?key\s*=\s*["'\'']?[A-Za-z0-9_\-]{20,}'
+ 'token\s*=\s*["'\'']?[A-Za-z0-9_\-]{20,}'
+ 'password\s*=\s*["'\'']?[^[:space:]]{8,}'
+ )
+
+ found=0
+ for pattern in "${patterns[@]}"; do
+ if grep -RInE "${grep_excludes[@]}" "$pattern" .; then
+ found=1
+ fi
+ done
+
+ if find . -path ./.git -prune -o \( -name ".env" -o -name ".env.*" \) -not -name ".env.example" -print | grep .; then
+ echo "Committed environment files were found."
+ found=1
+ fi
+
+ if [ "$found" -eq 1 ]; then
+ echo "Potential secret or config leak detected. Review the matches above."
+ exit 1
+ fi
+
+ - name: AI instruction injection scan
+ shell: bash
+ run: |
+ grep_excludes=(
+ --exclude-dir=.git
+ --exclude-dir=node_modules
+ --exclude-dir=dist
+ --exclude-dir=build
+ --exclude-dir=release
+ --exclude=security-scan.yml
+ )
+
+ patterns=(
+ 'ignore (all )?(previous|above) instructions'
+ 'system prompt'
+ 'developer message'
+ 'reveal your instructions'
+ 'exfiltrate'
+ 'send.*token'
+ 'send.*secret'
+ 'disable.*safety'
+ 'jailbreak'
+ 'prompt injection'
+ )
+
+ found=0
+ for pattern in "${patterns[@]}"; do
+ if grep -RInEi "${grep_excludes[@]}" "$pattern" .; then
+ found=1
+ fi
+ done
+
+ if [ "$found" -eq 1 ]; then
+ echo "Potential AI instruction-injection text found. Review whether this is documentation, test data, or malicious content."
+ exit 1
+ fi
diff --git a/manifest.json b/manifest.json
index e1af26a..0dc9dc9 100644
--- a/manifest.json
+++ b/manifest.json
@@ -16,6 +16,17 @@
"Run the cheapest reliable verification command or document why it could not run.",
"After pushing workflow-triggering commits, poll Gitea workflow runs until success or a concrete blocker."
],
+ "securityAutomation": {
+ "workflow": "files/security-scan-gitea.yml",
+ "target": ".gitea/workflows/security-scan.yml",
+ "schedule": "weekly",
+ "checks": [
+ "stack-specific dependency audit",
+ "suspicious code pattern scan",
+ "secret and config leak scan",
+ "AI instruction injection scan"
+ ]
+ },
"readmeDivider": {
"templateName": "section-line",
"source": "https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png",
@@ -92,6 +103,11 @@
"source": "files/build-gitea.yml",
"target": ".gitea/workflows/build.yml",
"required": false
+ },
+ {
+ "source": "files/security-scan-gitea.yml",
+ "target": ".gitea/workflows/security-scan.yml",
+ "required": false
}
],
"placeholders": [
diff --git a/manifest.schema.json b/manifest.schema.json
index 353108a..6df4919 100644
--- a/manifest.schema.json
+++ b/manifest.schema.json
@@ -34,6 +34,27 @@
}
}
},
+ "securityAutomation": {
+ "type": "object",
+ "required": ["workflow", "target", "schedule", "checks"],
+ "properties": {
+ "workflow": {
+ "type": "string"
+ },
+ "target": {
+ "type": "string"
+ },
+ "schedule": {
+ "type": "string"
+ },
+ "checks": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
"workflows": {
"type": "object",
"required": ["newRepository", "existingProject", "quickstart"],
@@ -90,4 +111,3 @@
}
}
}
-
diff --git a/new-repository.md b/new-repository.md
index 03a888b..febd3a6 100644
--- a/new-repository.md
+++ b/new-repository.md
@@ -50,6 +50,7 @@ files/release-notes.md -> docs/release-notes.md
files/blueprint.md -> blueprint.md
files/blueprint.json -> blueprint.json
files/build-gitea.yml -> .gitea/workflows/build.yml
+files/security-scan-gitea.yml -> .gitea/workflows/security-scan.yml
```
Skip `build-gitea.yml` when the project has no CI target yet. Skip README blueprint files when the project should keep a very small manual README.
@@ -156,6 +157,8 @@ upload artifacts
Only publish artifacts to a package registry when the artifact names and credentials are known.
+For releasable projects, config tools, apps, or repositories that process user data, secrets, or deployment files, also add `.gitea/workflows/security-scan.yml`. Keep the scheduled workflow conservative and review false positives before silencing checks.
+
### 7. Finish
Before final response: