Skip to content

Dev#12

Merged
SushantGautam merged 5 commits into
mainfrom
dev
Apr 20, 2026
Merged

Dev#12
SushantGautam merged 5 commits into
mainfrom
dev

Conversation

@SushantGautam

Copy link
Copy Markdown
Collaborator

No description provided.

- Introduced `SIMPLEAUDIT_VISUALIZER_EMAIL` environment variable to customize the contact email shown in the authentication overlay.
- Updated the README to reflect the new email configuration.
- Modified the server response to include the contact email.
- Adjusted the frontend to dynamically display the contact email based on server response.
- Added tests to verify default and custom contact email functionality.
Copilot AI review requested due to automatic review settings April 20, 2026 18:52
@SushantGautam
SushantGautam merged commit 7999375 into main Apr 20, 2026
3 checks passed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds optional secret-based authentication to the SimpleAudit visualization server/UI, and extends the visualizers to display an expected_behavior field in scenario results.

Changes:

  • Add optional X-Secret header auth to the FastAPI visualization endpoints plus a frontend auth overlay flow.
  • Normalize/render expected_behavior as a list in both visualizer.html and the standalone scenario_viewer.html.
  • Update visualization docs and example JSON to include expected_behavior, plus a small root README link tweak.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
simpleaudit/visualization/visualizer.html Adds auth overlay + authenticated fetch wrapper; renders expected_behavior in scenario details.
simpleaudit/visualization/server.py Adds env-configured secret gating for API routes and an /api/auth endpoint.
simpleaudit/visualization/scenario_viewer.html Adds expected_behavior normalization/rendering; changes header title to link to /.
simpleaudit/visualization/README.md Documents new auth environment variables and behavior.
examples/test_visualisation_results.json Updates examples to provide expected_behavior arrays instead of null.
README.md Updates LICENSE link to a GitHub URL.
Comments suppressed due to low confidence (1)

simpleaudit/visualization/server.py:198

  • The path traversal protection in get_json_file() relies on full_path.startswith(os.path.normpath(RESULTS_DIR)), which can be bypassed by sibling prefixes (e.g., /tmp/results2 starts with /tmp/results). Use a robust containment check like os.path.commonpath([full_path, RESULTS_DIR]) == os.path.normpath(RESULTS_DIR) or Path(full_path).resolve().is_relative_to(Path(RESULTS_DIR).resolve()).
@app.get("/api/json/{file_path:path}", dependencies=[Depends(check_secret)])
async def get_json_file(file_path: str):
    """Get the contents of a specific JSON file."""
    if not RESULTS_DIR:
        raise HTTPException(status_code=500, detail="Results directory not set")

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +164 to +178
is enabled. When the server has no secret configured it still
returns 200 but sets ``enabled`` to False.

The response also includes ``contact_email`` which is read from the
``SIMPLEAUDIT_VISUALIZER_EMAIL`` environment variable and defaults
to the original maintainer address. The frontend uses this to
populate the authentication overlay message.
"""
try:
check_secret(request)
except HTTPException as exc:
# propagate unauthorized status
raise

return JSONResponse(content={"ok": True, "enabled": bool(SECRET), "contact_email": CONTACT_EMAIL})

Copilot AI Apr 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/api/auth returns HTTP 401 when the secret is missing/invalid, which prevents the frontend from reading contact_email (and even enabled) from the response. This makes the SIMPLEAUDIT_VISUALIZER_EMAIL override ineffective when the overlay is shown. Consider returning a 200 with a JSON payload like {enabled: true, ok: false, contact_email: ...} for missing/invalid secrets (or include contact_email in the 401 body and have the client parse it).

Suggested change
is enabled. When the server has no secret configured it still
returns 200 but sets ``enabled`` to False.
The response also includes ``contact_email`` which is read from the
``SIMPLEAUDIT_VISUALIZER_EMAIL`` environment variable and defaults
to the original maintainer address. The frontend uses this to
populate the authentication overlay message.
"""
try:
check_secret(request)
except HTTPException as exc:
# propagate unauthorized status
raise
return JSONResponse(content={"ok": True, "enabled": bool(SECRET), "contact_email": CONTACT_EMAIL})
is enabled. It always returns 200 so the frontend can read both
``enabled`` and ``contact_email`` even when the secret is missing
or invalid.
The response also includes ``contact_email`` which is read from the
``SIMPLEAUDIT_VISUALIZER_EMAIL`` environment variable and defaults
to the original maintainer address. The frontend uses this to
populate the authentication overlay message.
"""
enabled = bool(SECRET)
token = request.headers.get("X-Secret")
ok = (not enabled) or (token == SECRET)
return JSONResponse(
content={
"ok": ok,
"enabled": enabled,
"contact_email": CONTACT_EMAIL,
}
)

Copilot uses AI. Check for mistakes.
Comment on lines +172 to +176
try:
check_secret(request)
except HTTPException as exc:
# propagate unauthorized status
raise

Copilot AI Apr 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

auth_check() wraps check_secret() in a try/except that immediately re-raises, and also binds exc without using it. This is dead code and can be removed (or handle the exception meaningfully) to avoid lint issues and keep the endpoint logic clear.

Suggested change
try:
check_secret(request)
except HTTPException as exc:
# propagate unauthorized status
raise
check_secret(request)

Copilot uses AI. Check for mistakes.

try {
const response = await fetch('/api/files');
const response = await apiFetch('/api/files');

Copilot AI Apr 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There’s a large indentation anomaly before const response = await apiFetch('/api/files');, which makes this block harder to read and suggests an accidental tab/spaces paste. Re-indent the try block consistently with surrounding code.

Suggested change
const response = await apiFetch('/api/files');
const response = await apiFetch('/api/files');

Copilot uses AI. Check for mistakes.
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span>SimpleAudit Scenario Viewer</span>
<a href="/" class="hover:underline text-indigo-700">SimpleAudit Scenario Viewer</a>

Copilot AI Apr 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The standalone viewer is documented as working completely offline; linking the title to href="/" will navigate away (and likely break) when opened via file:// or in offline contexts. Consider keeping this as plain text, or only rendering the link when served over HTTP(S) (or use a relative link that preserves offline usage).

Suggested change
<a href="/" class="hover:underline text-indigo-700">SimpleAudit Scenario Viewer</a>
<span class="text-indigo-700">SimpleAudit Scenario Viewer</span>

Copilot uses AI. Check for mistakes.
Comment on lines +15 to 17
By default the authentication overlay includes a contact email address. You can override it by setting `SIMPLEAUDIT_VISUALIZER_EMAIL` before starting the server


Copilot AI Apr 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This README states that setting SIMPLEAUDIT_VISUALIZER_EMAIL will change the contact email shown in the auth overlay, but with the current /api/auth behavior returning 401 for missing/invalid secrets, the frontend can’t read contact_email when the overlay is shown. Either adjust the API/frontend so the email is available pre-auth, or update the docs to match the actual behavior.

Suggested change
By default the authentication overlay includes a contact email address. You can override it by setting `SIMPLEAUDIT_VISUALIZER_EMAIL` before starting the server
`SIMPLEAUDIT_VISUALIZER_EMAIL` configures the server contact email, but with the current authentication flow that value is not exposed to unauthenticated clients before the secret key is entered.
In other words, do not expect the authentication overlay itself to reflect `SIMPLEAUDIT_VISUALIZER_EMAIL` unless the auth API/frontend is updated to make that information available pre-auth.

Copilot uses AI. Check for mistakes.
Comment on lines +155 to +159
if not SECRET:
return
token = request.headers.get("X-Secret")
if token != SECRET:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Unauthorized")

Copilot AI Apr 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Secret comparison in check_secret() uses a plain != string compare. If this endpoint can be reached by untrusted clients, prefer secrets.compare_digest(token or "", SECRET) to avoid timing leaks and to handle None cleanly.

Copilot uses AI. Check for mistakes.
Comment on lines +55 to +61
const resp = await fetch('/api/auth', {headers});
if (resp.status === 401) {
// key required
document.getElementById('auth-overlay').classList.remove('hidden');
document.getElementById('logout-button').classList.add('hidden');
return false;
}

Copilot AI Apr 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When /api/auth responds 401, ensureLoggedIn() returns before updating the contact email link, so the overlay can never reflect SIMPLEAUDIT_VISUALIZER_EMAIL overrides. If the server is updated to return contact_email even when unauthenticated, update this branch to parse the response (or call a non-authenticated endpoint) so the overlay shows the correct contact info.

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +34
const token = localStorage.getItem('visualizer_secret');
if (token) {
opts.headers['X-Secret'] = token;
}

Copilot AI Apr 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The secret is persisted in localStorage, which makes it accessible to any XSS on this origin and keeps it across browser restarts. If persistence isn’t required, prefer sessionStorage or keeping it in-memory; if it is required, document the risk and consider scoping/expiry (e.g., timestamp + re-prompt).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants