Back to skill

Security audit

Nova App Builder

Security checks for vulnerabilities and agentic risk

Overview

This skill appears intended to build and deploy Nova apps, but it uses risky credential handling and broad deployment defaults that users should review before installing.

Install only if you are comfortable letting the skill create files, push code, call the Nova API, deploy cloud infrastructure, and optionally perform on-chain registration. Prefer safer credential handling before use: do not embed GitHub tokens in remote URLs, avoid passing Nova API keys directly on the command line, review generated egress_allow settings, and use simple slug app names in an empty output directory.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (5)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/nova_deploy.py:55
Finding

Unrestricted Domain Egress Enabled by Default

Content
View full analysis
dict: return { "directory": directory, "app_listening_port": port, "egress_allow": ["**"], "enable_decentralized_kms": enable_kms, "enable_persistent_storage": enable_s3, "enable_s3_storage": enable_s3, ``` ### Technical Analysis The deployment configuration grants applications outbound access to every domain name by default through `egress_allow: ["**"]`. Basic application creation, build, health checking, and deployment do not inherently require unrestricted application-level egress. The wildcard does not cover direct IP addresses according to the project documentation, but it still permits communication with any attacker-controlled domain. If application code or one of its dependencies is compromised, this permission provides a ready-made channel for command-and-control traffic or data exfiltration. This exceeds least privilege because egress is enabled independently of the features or external services selected by the user. ### Attack Path 1. A malicious dependency, compromised source repository, or application vulnerability results in attacker-controlled code running inside the enclave application. 2. The generated deployment already permits connections to all domain names. 3. The attacker registers or controls an external domain. 4. The compromised application sends enclave data, service responses, or application secrets to that domain. 5. Network policy does not block the transmission because the wildcard authorizes it. ### Impact Assessment An attacker who obtains code ex ...[truncated 416 chars]
Remediation
View remediation
` arguments. - Populate the allowlist only with domains required by enabled features. - Require an explicit acknowledgement before allowing `"**"`. - Provide narrowly scoped presets for S3, KMS, and supported chain RPC services. - Add an `egress_deny` policy for metadata, private, loopback, and link-local address ranges unless a specific platform feature demonstrably requires them. - Document that wildcard egress materially weakens enclave isolation. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/nova_deploy.py:334
Finding

Nova API Key Exposed Through Command-Line Arguments

Content
View full analysis
``` ### Technical Analysis Requiring the API key as a command-line argument places the secret in the process argument vector. Depending on the operating system and process-isolation configuration, command-line arguments may be visible to other local users or monitoring software through process listings or process metadata. The command can also remain in shell history or be captured by CI logs, terminal recording, Agent transcripts, debuggin ...[truncated 1087 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:43
Finding

GitHub Personal Access Token Persisted in Git Remote URL

Content
View full analysis
/.git git push origin main ``` ``` ### Technical Analysis The shell expands `${GH_TOKEN}` before executing `git remote set-url`. Git then stores the expanded URL, including the plaintext token, in the repository's `.git/config` file. The credential may consequently be exposed through filesystem access, repository diagnostics, support bundles, backups, workspace archives, configuration inspection, or commands that display the remote URL. Depending on shell and automation behavior, the command may also be recorded in logs. The documented token has repository content write permission, making disclosure security-sensitive. ### Attack Path 1. A user exports a valid fine-grained GitHub PAT as `GH_TOKEN`. 2. The user follows the documented `git remote set-url` command. 3. The shell expands the variable and Git persists the credential-bearing URL in `.git/config`. 4. An attacker, local process, archive consumer, or diagnostic-log reader obtains the repository configuration. 5. The attacker extracts the PAT from the remote URL. 6. The attacker uses the PAT to read or modify repositories within its granted scope. 7. Modified source may subsequently be built and deployed by Nova Platform. ### Impact Assessment An attacker can obtain the GitHub permissions assigned to the token. Under the recommended permissions, this includes repository content read and write access for repositories selected when the fine-grained token was created. Source modification is particularly significant ...[truncated 170 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/scaffold.py:17
Finding

Path Traversal Allows Scaffolding Outside the Selected Output Directory

Content
View full analysis
Path: dest = out / name if dest.exists(): print(f"[warn] Directory already exists: {dest} — files will be overwritten") shutil.copytree(str(TEMPLATE_DIR), str(dest), dirs_exist_ok=True) # Rename Dockerfile.txt -> Dockerfile and replace port placeholder dockerfile_template = dest / "Dockerfile.txt" dockerfile = dest / "Dockerfile" text = dockerfile_template.read_text() text = text.replace("{{APP_PORT}}", str(port)) dockerfile.write_text(text) dockerfile_template.unlink() ``` The only name transformation performed by the command-line entry point is: ```python args = p.parse_args() name = args.name.lower().replace(" ", "-") out = Path(args.out).resolve() out.mkdir(parents=True, exist_ok=True) if not TEMPLATE_DIR.exists(): print(f"[error] Template not found: {TEMPLATE_DIR}", file=sys.stderr) sys.exit(1) scaffold(name, args.desc, args.port, out) ``` ### Technical Analysis The application name is joined directly to the output path without validation or containment checking. Lowercasing and replacing spaces does not remove `..`, path separators, or absolute paths. Consequently, a name such as `../../target` can escape the selected output directory. An absolute name can also cause `pathlib` path composition to discard the intended base directory. The use of `dirs_exist_ok=True` then overwrites files with matching template paths in an existing destination. The warning does not require user confirmation and does not prevent the overwrite. ### Attack Path 1. An attacker controls or influences the application name passed to the scaffold command. 2. The attacker supplies a traversal value such as `../../victim-proje ...[truncated 987 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
assets/app-template/enclave/requirements.txt:1
Finding

Unpinned Dependencies and Mutable Base Image Produce Non-Reproducible Builds

Content
View full analysis
=0.111.0 uvicorn[standard]>=0.29.0 # HTTP client — proxy-aware (required for egress inside the enclave) # Never use requests or urllib in enclave code; they bypass the Odyn egress proxy. httpx>=0.27.0 ``` The container image is also referenced by a mutable tag: ```dockerfile FROM python:3.11-slim WORKDIR /app COPY enclave/requirements.txt . RUN pip install --no-cache-dir -r requirements.txt ``` ### Technical Analysis The `>=` constraints allow future package versions to be installed without changes to the audited project. The `python:3.11-slim` image tag can likewise resolve to different image content over time. As a result, rebuilding the same source revision may execute dependency or base-image code that was not present during the audit. This weakens build provenance and makes security review of the resulting enclave image non-deterministic. No malicious package name or confirmed dependency compromise was identified. The vulnerability is the absence of immutable version and artifact constraints. ### Attack Path 1. A generated application is built at a later date. 2. Package resolution selects newer FastAPI, Uvicorn, HTTPX, or transitive dependency releases because only minimum versions are specified. 3. The mutable base-image tag may also resolve to a newer image. 4. A newly introduced vulnerability or compromised upstream artifact becomes part of the enclave image. 5. The unreviewed code executes during installation, application startup, or request processing. ### Impact Assessment A compromised or vulnerable dependency can execute with the privileges of the containerized application. It may access application data, invoke local Odyn APIs available t ...[truncated 312 chars]
Remediation
View remediation
``` - Use reviewed dependency-update automation rather than automatically accepting all future versions. - Generate a software bill of materials for each build. - Scan both Python dependencies and the base image before deployment. - Add an unprivileged application user to the Dockerfile and run Uvicorn under that account. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (41)

Tp4

High
Category
MCP Tool Poisoning
Confidence
88% confidence
Finding

The declared description says this skill handles the full lifecycle of creating and deploying Nova apps, including scaffolding, coding, building into a Docker image, pushing, deploying, and verifying a running deployment. The supplied code chunk only defines the runtime application template for the enclave service itself. It starts a FastAPI server, exposes required Nova endpoints, returns attestation data, and demonstrates enclave signing behavior via Odyn. Those behaviors are consistent with writing enclave application code, but the code does not implement the broader claimed build/deploy lifecycle. Therefore the description materially overstates what this code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared purpose focuses on application lifecycle automation for Nova Platform apps: scaffold, code generation, container build, image push, deployment, and runtime verification. The actual code chunk does none of those deployment/build tasks. Instead, it exposes a runtime helper/client for interacting with Odyn internal enclave services over HTTP. These are materially different capabilities and a different primary purpose. While such a client could be used as part of a Nova app template, this specific code does not implement app creation or deployment behavior described in the skill.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

The skill requires a GitHub personal access token and demonstrates embedding it directly in a remote URL. In agent or shared-shell environments this is dangerous because tokens may leak through command history, process listings, git config, logs, crash reports, or echoed commands, enabling repository compromise.

Content

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

md
- **GitHub repo + GitHub PAT**: Used only to push your app code to GitHub. Nova Platform then builds from the repo URL. The PAT is not passed to Nova Platform.

  **GitHub PAT setup**:
  1. GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens
  2. Required permissions: **Contents** (Read & Write), **Metadata** (Read)
  3. Push with token:
     ```bash

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

md
REPO="https://github.com/you/my-app"

# 1. Create app — 'advanced' is the only config field needed
SQID=$(curl -sX POST "$BASE/apps" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

md
echo "App sqid: $SQID"

# 2. Create new version (build) — repo URL comes from app record, not repeated here
BUILD_ID=$(curl -sX POST "$BASE/apps/$SQID/builds" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"git_ref":"main","version":"1.0.0"}' \

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

md
# 3. Poll build
while true; do
  STATUS=$(curl -s "$BASE/builds/$BUILD_ID/status" \
    -H "Authorization: Bearer $TOKEN" \
    | python3 -c "import sys,json; print(json.load(sys.stdin).get('status',''))")
  echo "Build: $STATUS"

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

md
# 4. Deploy this version — specify region and tier
# region options: ap-south-1 (default), us-east-1, us-west-1, eu-west-1
# tier options: standard (2vCPU/5GiB), performance (6vCPU/13GiB)
DEPLOY_ID=$(curl -sX POST "$BASE/apps/$SQID/deployments" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"build_id\":$BUILD_ID,\"region\":\"ap-south-1\",\"tier\":\"standard\"}" \

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

md
# 5. Poll deployment
while true; do
  RESP=$(curl -s "$BASE/deployments/$DEPLOY_ID/status" -H "Authorization: Bearer $TOKEN")
  STATE=$(echo $RESP | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('deployment_state',''))")
  echo "Deployment state: $STATE"
  [ "$STATE" = "running" ] && break

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

md
done

# 6. Get app URL (hostname from detail, or use unified status)
curl -s "$BASE/apps/$SQID/detail" -H "Authorization: Bearer $TOKEN" \
  | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['app'].get('hostname',''))"

# Tip: GET /api/apps/{sqid}/status gives the full lifecycle in one call:

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

md
done

# 6c. Generate ZK proof (SP1-based)
curl -sX POST "$BASE/zkproof/generate" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"deployment_id\": $DEPLOY_ID}"

Cloud Metadata Access

High
Category
Server-Side Request Forgery
Confidence
97% confidence
Finding

The guidance explicitly allows 169.254.169.254 in egress rules, which is the cloud metadata endpoint and a classic SSRF target. Even if intended for platform plumbing, normalizing metadata access in app/network policy increases the chance that vulnerable app code or malicious dependencies can retrieve instance credentials or environment metadata.

Content

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

md
| App stuck in `provisioning` >10 min | Check app logs via `GET /api/apps/{sqid}/detail` |
| `httpx` request fails inside enclave | Add domain to `advanced.egress_allow`. Note: `"**"` matches domains only — add `"0.0.0.0/0"` for direct IP connections |
| Direct IP connection blocked | `"**"` does NOT cover IPs. Add `"0.0.0.0/0"` (IPv4) and/or `"::/0"` (IPv6) to `egress_allow` |
| S3 fails | Ensure `169.254.169.254` and S3 endpoint are in egress allow list |
| `/v1/kms/*` returns 400 | Ensure `enable_decentralized_kms: true` and `enable_helios_rpc: true` in `advanced` at app creation |
| App Wallet unavailable | Ensure `enable_app_wallet: true` in `advanced` at app creation |
| Proxy not respected for external calls | Use `httpx` for external HTTP calls (proxy-aware). `requests`/`urllib` may bypass the egress proxy. Note: `requests` is fine for internal Odyn calls (localhost). |

Possible Typosquatting: 'uvicorn' resembles popular package 'gunicorn'

High
Category
Supply Chain
Confidence
70% confidence
Finding

Package name closely resembles a popular package, suggesting possible typosquatting. Attackers publish malicious packages with similar names to trick developers into installing them.

Content

No source excerpt is available for this finding.

Cloud Metadata Access

High
Category
Server-Side Request Forgery
Confidence
90% confidence
Finding

The documentation recommends allowing access to 169.254.169.254, the cloud metadata service, as part of egress configuration. In an agent skill that scaffolds and deploys arbitrary app code, encouraging metadata access can materially increase SSRF and credential-exposure risk if the deployed app or a dependency is compromised, especially when broad egress like 0.0.0.0/0 is also documented nearby.

Content

Scanner excerpt · references/nova-api.md (reported line 106)May include surrounding context.

md
| `"news.ycombinator.com"` | Exact domain |
| `"0.0.0.0/0"` | All IPv4 addresses |
| `"::/0"` | All IPv6 addresses |
| `"169.254.169.254"` | Exact IP (IMDS — required for S3/KMS) |
| `"66.254.33.0/24"` | IPv4 CIDR |

**To allow everything** (domains + IPs):

Cloud Metadata Access

High
Category
Server-Side Request Forgery
Confidence
93% confidence
Finding

The explicit example egress_allow: ["**", "169.254.169.254"] normalizes allowing unrestricted domain egress plus cloud metadata access. In the context of a build-and-deploy skill for user-supplied enclave apps, this meaningfully raises the blast radius of SSRF, secret harvesting, and cloud-environment introspection if application code is vulnerable.

Content

Scanner excerpt · references/nova-api.md (reported line 116)May include surrounding context.

For AWS S3/KMS (IMDS required):

json
"egress_allow": ["**", "169.254.169.254"]

A request is allowed if it matches at least one allow pattern AND no deny pattern.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/nova-api.md (reported line 438)May include surrounding context.

Build Management

text
DELETE /api/apps/{app_sqid}/builds/{build_id}               # Delete a build
POST   /api/apps/{app_sqid}/builds/{build_id}/enroll        # Enroll version on-chain
POST   /api/apps/{app_sqid}/builds/{build_id}/sync          # Sync build status
POST   /api/apps/{app_sqid}/builds/{build_id}/retry         # Retry a failed build

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/nova-api.md (reported line 511)May include surrounding context.

text
GET  /api/auth/api-keys                # List API keys (last_used_at is best-effort)
POST /api/auth/api-keys                # Create a new API key
DELETE /api/auth/api-keys/{api_key_id} # Revoke an API key (204 No Content)

Profile

Cloud Metadata Access

High
Category
Server-Side Request Forgery
Confidence
90% confidence
Finding

Code accesses a cloud instance metadata endpoint (e.g. 169.254.169.254). A single request can return temporary IAM credentials, making this a high-value SSRF target for credential theft.

Content

Scanner excerpt · references/odyn-api.md (reported line 180)May include surrounding context.

{ "enable_s3_storage": true, "enable_s3_kms_encryption": false, "egress_allow": ["169.254.169.254", "s3.us-east-1.amazonaws.com"] }

text

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill describes operations that require shell, filesystem, environment, and network access, but it does not declare any explicit tool scope or permission boundaries. In an agent system, this creates an authorization gap where the runtime may grant broader capabilities than users expect, increasing the risk of unintended command execution, file modification, or outbound requests.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The trigger phrases are broad enough that the skill may activate on loosely related requests about building apps, TEEs, or Nova. Over-broad invocation can cause an agent to enter a workflow that requests API keys, GitHub tokens, shell access, and deployment actions when the user may have intended only to ask conceptual questions.

Content

No source excerpt is available for this finding.

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 280)May include surrounding context.

md
REPO="https://github.com/you/my-app"

# 1. Create app — 'advanced' is the only config field needed
SQID=$(curl -sX POST "$BASE/apps" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The examples normalize highly permissive egress settings such as egress_allow:["**"] without a strong warning that this effectively permits unrestricted outbound access to domains. In the context of enclave or agent-generated apps, broad egress materially increases exfiltration, callback, and supply-chain risk if the app logic is compromised or malicious.

Content

No source excerpt is available for this finding.

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 307)May include surrounding context.

md
echo "App sqid: $SQID"

# 2. Create new version (build) — repo URL comes from app record, not repeated here
BUILD_ID=$(curl -sX POST "$BASE/apps/$SQID/builds" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"git_ref":"main","version":"1.0.0"}' \

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 328)May include surrounding context.

md
# 4. Deploy this version — specify region and tier
# region options: ap-south-1 (default), us-east-1, us-west-1, eu-west-1
# tier options: standard (2vCPU/5GiB), performance (6vCPU/13GiB)
DEPLOY_ID=$(curl -sX POST "$BASE/apps/$SQID/deployments" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"build_id\":$BUILD_ID,\"region\":\"ap-south-1\",\"tier\":\"standard\"}" \

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
86% confidence
Finding

The instruction that the script will automatically execute steps 6a–6d and poll until complete encourages autonomous state-changing actions across on-chain registration steps. In agent contexts, this can lead to irreversible or costly actions being taken without granular user review of each registration step.

Content

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

bash
python3 scripts/nova_deploy.py ... --onchain

The script will automatically execute steps 6a–6d and poll until complete.

Manually via API — 4-step sequence:

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 402)May include surrounding context.

md
done

# 6c. Generate ZK proof (SP1-based)
curl -sX POST "$BASE/zkproof/generate" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"deployment_id\": $DEPLOY_ID}"

Static analysis

No suspicious patterns detected.