T05 · Unauthorized Access and Privilege Escalation
- Location
api/app/api/routes/auth.py:25- Finding
Magic-Link Token Disclosure Enables Authentication Bypass
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The MoltFundMe skill instructions are mostly coherent, but the bundled platform and deployment materials contain high-impact authentication, KYC, credential, and host-privilege risks that should be reviewed before use.
Install or use this only with explicit user approval for any public post, upvote, evaluation, advocacy, profile change, or upload. Do not follow the production deployment guide as-is: use least-privilege deployment accounts, unique SSH keys, read-only package tokens, pinned and verified installers, hardened secret storage, and proper KYC review before accepting real campaigns or donations.
api/app/api/routes/auth.py:25Magic-Link Token Disclosure Enables Authentication Bypass
api/app/api/routes/kyc.py:126KYC Submissions Are Automatically Approved Without Identity Verification
api/app/api/routes/kyc.py:75KYC Documents Receive Extension-Only Validation and Potentially Permissive Storage
DEPLOY.md:12Deployment Account Receives Unrestricted Passwordless Root Privileges
DEPLOY.md:19Root SSH Authorization Is Duplicated onto a Root-Equivalent Deployment Account
DEPLOY.md:55Mutable Remote Installer Is Downloaded and Executed Without Integrity Verification
api/app/api/routes/auth.py:64Internal Exception Details Are Returned in HTTP Responses
Creating and populating /home/moltfund/.ssh/ from root's SSH authorization material provisions credentialed access in a way that reuses sensitive trust relationships. Because the new user is later made highly privileged, this turns simple account setup into a credential-propagation risk.
# Copy SSH keys from root so you can SSH in as the new user
mkdir -p /home/moltfund/.ssh
cp /root/.ssh/authorized_keys /home/moltfund/.ssh/
chown -R moltfund:moltfund /home/moltfund/.ssh
chmod 700 /home/moltfund/.ssh
chmod 600 /home/moltfund/.ssh/authorized_keys
Creating and populating /home/moltfund/.ssh/ from root's SSH authorization material provisions credentialed access in a way that reuses sensitive trust relationships. Because the new user is later made highly privileged, this turns simple account setup into a credential-propagation risk.
# Copy SSH keys from root so you can SSH in as the new user
mkdir -p /home/moltfund/.ssh
cp /root/.ssh/authorized_keys /home/moltfund/.ssh/
chown -R moltfund:moltfund /home/moltfund/.ssh
chmod 700 /home/moltfund/.ssh
chmod 600 /home/moltfund/.ssh/authorized_keys
This line finalizes permissions on a new user's SSH authorization file that originated from root's authorized keys, cementing credential reuse rather than distinct identity management. The danger is the inherited root-trusted access, not the permission mode itself.
cp /root/.ssh/authorized_keys /home/moltfund/.ssh/ chown -R moltfund:moltfund /home/moltfund/.ssh chmod 700 /home/moltfund/.ssh chmod 600 /home/moltfund/.ssh/authorized_keys
---
This line finalizes permissions on a new user's SSH authorization file that originated from root's authorized keys, cementing credential reuse rather than distinct identity management. The danger is the inherited root-trusted access, not the permission mode itself.
cp /root/.ssh/authorized_keys /home/moltfund/.ssh/ chown -R moltfund:moltfund /home/moltfund/.ssh chmod 700 /home/moltfund/.ssh chmod 600 /home/moltfund/.ssh/authorized_keys
---
Instructing users to generate a GitHub Personal Access Token with both read:packages and write:packages for VM registry login grants more privilege than necessary for pull-only deployment. Over-privileged long-lived credentials increase the impact of token leakage, including unauthorized image publication.
# Create GitHub Personal Access Token (PAT) if you don't have one:
# Go to https://github.com/settings/tokens
# Generate new token (classic) with scopes: read:packages, write:packages
The guide explicitly notes that registry credentials are stored in ~/.docker/config.json but does not instruct the operator to protect that file with a credential helper, least privilege, or file-permission checks. If exposed, an attacker could pull or possibly push images depending on token scope, enabling supply-chain abuse.
docker pull ghcr.io/sahanico/moltfundme/api:latest docker pull ghcr.io/sahanico/moltfundme/web:latest
Creating a .env file for production secrets is common, but the guide gives no instructions for permission hardening, exclusion from backups/logs, or secret-management alternatives. This can lead to accidental exposure of application secrets such as SECRET_KEY and database configuration.
git clone git@github.com:sahanico/moltfundme.git molt
cd molt
# Create .env from example
cp .env.example .env
# Edit .env with production values
Editing .env interactively to insert production secrets without accompanying guidance on terminal history, editor swap files, file permissions, or secret storage creates avoidable credential exposure risk. The issue is especially relevant because the document is otherwise positioned as operational guidance.
cd molt
# Create .env from example
cp .env.example .env
# Edit .env with production values
nano .env
The instructions enumerate sensitive production values for insertion into .env but omit controls for protecting them at rest and in operational workflows. This can result in long-lived plaintext secrets being broadly accessible on disk.
# Create .env from example
cp .env.example .env
# Edit .env with production values
nano .env
# Required values:
# - ENV=production
The document specifically calls for a SECRET_KEY in .env yet provides no guidance on entropy requirements, storage protections, or rotation. Poor handling of this key could enable session forgery, token compromise, or broader application-level attacks depending on usage.
cp .env.example .env
# Edit .env with production values
nano .env
# Required values:
# - ENV=production
# - SECRET_KEY=<generate secure random string>
The description claims substantial crowdfunding-related functionality, but the provided code chunk does not implement any of it. Since the code only contains a comment ('API routes') and no executable logic, the declared purpose is not supported by the actual behavior shown. This is a material description-to-code mismatch due to absence of the advertised capabilities in the supplied code.
The declared purpose describes end-user crowdfunding and campaign advocacy functionality specific to MoltFundMe. The provided code does not browse campaigns, evaluate causes, participate in discussions, handle donations, or interact with MoltFundMe campaign data. Instead, it provides backend access-control helpers for identifying agents and creators from headers/tokens and enforcing KYC requirements. This is a materially different primary purpose and introduces undeclared security/authentication capabilities unrelated to the stated description.
The declared description focuses on campaign discovery and advocacy activity on MoltFundMe. However, this code chunk is specifically an agents API module for identity/profile management. Its primary functions are creating agent accounts, issuing credentials, updating profiles, uploading avatars, and listing agent standings. While there is some relation to advocacy through leaderboard filtering and recent advocacy summaries, the main behavior is not campaign browsing, cause evaluation, donation participation, or war room discussion access. The API key creation and avatar file upload are also undeclared capabilities. Therefore the description does not accurately represent this code chunk's actual behavior.
The declared description says this skill is for interacting with MoltFundMe crowdfunding campaigns and advocacy features. However, the supplied code is entirely focused on auth: generating magic-link tokens, persisting them, verifying expiration/usage, creating or retrieving user records, issuing JWTs, and handling logout. There is no campaign browsing, cause evaluation, war room discussion participation, karma earning, crowdfunding data access, or crypto donation functionality in this chunk. This is a materially different primary purpose, so the description does not accurately represent the code's behavior.
The code does relate to MoltFundMe crowdfunding campaigns, so part of the declared domain is accurate. However, the declared description emphasizes browsing, advocacy participation, war room discussions, and earning karma. This code chunk does not implement advocacy actions, war room discussion features, or karma-related behavior. Instead, it exposes substantial campaign administration and operational capabilities that are not declared: creating, editing, and cancelling campaigns; uploading and deleting campaign images; listing donations; generating social crawler OG pages; and refreshing blockchain balances with withdrawal detection and notification logic. Those are materially different backend capabilities beyond simple browsing/advocacy, so the description does not accurately represent the code's actual behavior.
The declared description emphasizes public-facing MoltFundMe campaign discovery and advocacy features: discovering campaigns, evaluating causes, joining discussions, donating/advocating context, and earning karma. This code instead implements a backend endpoint for authenticated creators to retrieve their own campaigns. It uses creator authentication, queries campaigns by creator_id, includes cancelled campaigns, paginates results, and calculates campaign metrics such as donation counts, distinct donor counts, advocate counts, and creator verification status. That is a materially different function from browsing or advocating for campaigns. While it is still within the broader MoltFundMe/campaign domain, the primary behavior here is creator dashboard data retrieval, which is not accurately represented by the declared description.
The declared description is about browsing and advocating for crowdfunding campaigns on MoltFundMe, but the code is entirely focused on creator identity verification workflows. It exposes endpoints for KYC status, KYC document submission, and submission history. It handles sensitive document uploads and updates creator verification state, which are materially different capabilities from campaign discovery, advocacy, war room participation, or karma earning. This is a clear description-behavior mismatch.
The declared description promises substantial MoltFundMe-related functionality, but the provided code does not implement any of it. The code chunk is effectively a placeholder (init.py with only a comment), so the actual behavior does not match the declared primary purpose.
The declared description suggests a feature for interacting with MoltFundMe campaigns and advocacy workflows. However, the supplied code does not browse campaigns, evaluate causes, participate in discussions, process donations, or handle karma. Its purpose is purely infrastructural: loading and validating application settings for a backend service. This is a materially different primary purpose from the declared user-facing crowdfunding functionality, so the description does not accurately represent the code.
The declared description is about interacting with MoltFundMe crowdfunding campaigns and advocacy workflows. The supplied code does not browse campaigns, evaluate causes, support discussions, handle donations, or perform any crowdfunding-related actions. Instead, it provides backend infrastructure for limiting agent registration attempts by IP address. This is a materially different primary purpose and represents unrelated functionality not reflected in the declared description.
The declared description says the skill should help users browse and advocate for MoltFundMe crowdfunding campaigns. However, the supplied code does not contain any campaign discovery, advocacy, discussion, donation, or MoltFundMe-specific logic. Its primary purpose is backend security infrastructure for credential and token handling. This is a materially different purpose and constitutes undeclared capabilities unrelated to the declared skill behavior.
The declared purpose is an end-user feature focused on browsing and advocating for crowdfunding campaigns on MoltFundMe. The actual code does not implement any campaign discovery, advocacy, donations, discussions, karma, or MoltFundMe-specific functionality. Instead, it provides generic backend middleware for setting security-related HTTP headers on responses. This is a materially different primary purpose and an unrelated capability, so it is a clear mismatch.
The declared description promises a user-facing crowdfunding advocacy skill centered on MoltFundMe, but the provided code chunk is only an empty database module stub with no functional logic. This is a material mismatch because the actual code does not exhibit the claimed primary purpose or capabilities.
This code chunk is generic backend database setup, not application logic for browsing or advocating for crowdfunding campaigns. While database access could support such a system, the supplied code itself does not implement any MoltFundMe-specific behavior, campaign operations, crypto donation handling, or user-facing advocacy features described in the skill. The primary purpose is materially different from the declared description, so this is a clear mismatch.
There is a clear mismatch between the declared purpose and the actual code behavior. The description promises end-user MoltFundMe crowdfunding features, but the code only initializes a database asynchronously. This is infrastructure/setup functionality, not campaign discovery, advocacy, discussion, or donation support. No MoltFundMe-specific logic or user-facing crowdfunding behavior is present in the supplied code chunk.
Detected: suspicious.env_credential_access, suspicious.exposed_secret_literal