T05 · Unauthorized Access and Privilege Escalation
- Location
backend/app.py:414- Finding
Unauthenticated Administrative and State-Changing Endpoints
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This appears to be a real pixel-office dashboard, but public use would expose unauthenticated controls, reusable join keys, local memory snippets, and XSS-prone pages.
Use this only as a local or isolated demo until it is hardened. Before public exposure, add authentication for all control and memo endpoints, replace bundled join keys with deployment-specific secrets, disable or curate memory summaries, fix innerHTML rendering, align the documented port with the backend, and review/update dependencies.
backend/app.py:414Unauthenticated Administrative and State-Changing Endpoints
join-keys.json:2Public Reusable Default Join Credentials Allow Unauthorized Enrollment
frontend/index.html:781Stored Cross-Site Scripting Through Remote Agent Names
frontend/index.html:501Stored Cross-Site Scripting Through Memory Summary Content
office-agent-push.py:187Free-Form Local Work Details Are Transmitted Externally Despite a Status-Only Privacy Claim
SKILL.md:68Public-Tunnel Instructions Target a Different Port Than the Backend Uses
backend/app.py:742Unauthenticated Memory Summary Endpoint Can Disclose Incompletely Redacted Agent Memory
The script trusts LOCAL_STATUS_URL from an environment variable and sends a bearer token to whatever URL is provided. If that variable is manipulated, the script can be turned into an SSRF-style proxy or tricked into exfiltrating the local status token and polling arbitrary internal or external endpoints.
headers = {}
if LOCAL_STATUS_TOKEN:
headers["Authorization"] = f"Bearer {LOCAL_STATUS_TOKEN}"
r = requests.get(LOCAL_STATUS_URL, headers=headers, timeout=5)
if r.status_code == 200:
data = r.json()
state = normalize_state(data.get("state", "idle"))
The skill description focuses on easy dashboard deployment, but the documented behavior includes reading local memory files, exposing their content through an endpoint, and mutating shared state through backend APIs. These extra behaviors materially expand the data-access and attack surface beyond what a user would reasonably expect from the description.
The skill description focuses on easy dashboard deployment, but the documented behavior includes reading local memory files, exposing their content through an endpoint, and mutating shared state through backend APIs. These extra behaviors materially expand the data-access and attack surface beyond what a user would reasonably expect from the description.
The skill description focuses on easy dashboard deployment, but the documented behavior includes reading local memory files, exposing their content through an endpoint, and mutating shared state through backend APIs. These extra behaviors materially expand the data-access and attack surface beyond what a user would reasonably expect from the description.
The skill description focuses on easy dashboard deployment, but the documented behavior includes reading local memory files, exposing their content through an endpoint, and mutating shared state through backend APIs. These extra behaviors materially expand the data-access and attack surface beyond what a user would reasonably expect from the description.
The skill description focuses on easy dashboard deployment, but the documented behavior includes reading local memory files, exposing their content through an endpoint, and mutating shared state through backend APIs. These extra behaviors materially expand the data-access and attack surface beyond what a user would reasonably expect from the description.
The skill description focuses on easy dashboard deployment, but the documented behavior includes reading local memory files, exposing their content through an endpoint, and mutating shared state through backend APIs. These extra behaviors materially expand the data-access and attack surface beyond what a user would reasonably expect from the description.
The skill description focuses on easy dashboard deployment, but the documented behavior includes reading local memory files, exposing their content through an endpoint, and mutating shared state through backend APIs. These extra behaviors materially expand the data-access and attack surface beyond what a user would reasonably expect from the description.
The skill description focuses on easy dashboard deployment, but the documented behavior includes reading local memory files, exposing their content through an endpoint, and mutating shared state through backend APIs. These extra behaviors materially expand the data-access and attack surface beyond what a user would reasonably expect from the description.
The skill description focuses on easy dashboard deployment, but the documented behavior includes reading local memory files, exposing their content through an endpoint, and mutating shared state through backend APIs. These extra behaviors materially expand the data-access and attack surface beyond what a user would reasonably expect from the description.
The skill description focuses on easy dashboard deployment, but the documented behavior includes reading local memory files, exposing their content through an endpoint, and mutating shared state through backend APIs. These extra behaviors materially expand the data-access and attack surface beyond what a user would reasonably expect from the description.
The README says the backend reads records from memory/*.md and applies only 'basic privacy sanitization' before display, but it does not warn that historical notes may still contain sensitive content. In this skill's context, surfacing prior work summaries through a UI or public endpoint can expose internal project details, personal data, or secrets that simple sanitization misses.
The documentation advertises guest join and continuous status push capabilities without warning that invited agents can keep submitting data into the shared dashboard. That omission can cause users to trust this feature too broadly, increasing the risk of spoofed statuses, unwanted data injection, or unauthorized persistence if join keys or access controls are weak.
The README explicitly encourages exposing the dashboard over Cloudflare Tunnel or another public domain, but it does not pair that guidance with clear warnings about authentication, authorization, or privacy risks. In the context of a dashboard that shows agent presence, status, and yesterday memo data, this can lead users to unintentionally publish operational or sensitive information to the internet.
The skill instructs the agent to use shell, network, and filesystem operations but does not declare any explicit tool scope or permission boundaries. This increases the chance of overbroad execution, especially because the steps include cloning code, installing dependencies, launching a server, and exposing it publicly.
The skill recommends exposing a locally hosted dashboard to the public internet via Cloudflare Tunnel and suggests alternative reverse proxies, but it does not prominently warn about privacy, authentication, or unintended data exposure. In this skill's context, that omission is more dangerous because the same document also references agent state updates, join keys, and yesterday-memo content that may be visible once exposed.
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.
def save_state(state: dict):
"""Save state to file"""
with open(STATE_FILE, "w", encoding="utf-8") as f:
json.dump(state, f, ensure_ascii=False, indent=2)
The /join-agent endpoint contradicts the intended approval flow by immediately setting authStatus to approved for any requester who presents a valid join key. This weakens access control: anyone who obtains or guesses a reusable key can register an agent and begin pushing state without human review, which is especially risky because the skill is designed for public/multi-agent remote access.
The dependency is pinned to Flask 3.0.2, and the static analysis indicates it is affected by a published advisory related to missing Vary: Cookie handling for some session access patterns. In a web UI skill that exposes dashboards, mobile access, and public internet access, incorrect cache variation on cookie-bearing responses can lead to cache poisoning or cross-user content/session mix-ups under certain deployment configurations.
The file contains extensive hard-coded Chinese UI text, status labels, and messages, with no indication that language selection is configurable or that the feature is intentionally region-specific. That creates a locale policy concern because the skill effectively forces a specific language on all users.
Server-provided memo content is inserted with innerHTML after only replacing newlines, so any HTML in data.memo will be interpreted by the browser. If an attacker can influence the memo content, this becomes a straightforward stored or reflected XSS path that can execute script in users' sessions, alter the UI, or exfiltrate sensitive data.
The manifest describes a one-click office UI for deployment, agent participation, visualization, mobile viewing, and public access. This file also implements a client-side function that POSTs to /set_state to change backend state, which goes beyond passive visualization and introduces a control capability not stated in the skill description.
The manifest promises a UI for deploying and visualizing a multi-agent office, implying display of real participating agents. The code unconditionally creates a fake agent_nika and periodically mutates its state with setInterval, meaning the UI can display fabricated agent presence and activity rather than only actual backend-driven status.
The memo content returned from /yesterday-memo is inserted with innerHTML after only replacing newlines with
, so any HTML delivered by the backend will execute or render in the page. In this dashboard context, that creates a straightforward stored or reflected XSS path if memo content can be influenced by an agent, operator, or compromised backend data source.
The guest agent list is built by interpolating untrusted fields like name, authStatus, state, and agentId into an HTML string assigned to list.innerHTML, including inside inline onclick handlers and data-* attributes. An attacker controlling those values could inject markup or JavaScript, leading to DOM XSS and potentially arbitrary actions in the dashboard such as approving, rejecting, or removing agents through the existing privileged endpoints.
No suspicious patterns detected.