Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 34 additions & 30 deletions .github/ETHICS_QUESTIONNAIRE.MD
Original file line number Diff line number Diff line change
@@ -1,36 +1,40 @@
**Ethics & Regulatory Questionnaire**
*This PR cannot be merged until this form is completed.*

Please reply to this comment and answer all questions below (you can copy-paste and fill it).

1. Does this change involve any of the following? (check all that apply)
- [ ] Training or fine-tuning of AI/ML models
- [ ] Inference/serving of AI/ML models in production
- [ ] Processing of personal data (PII, health, biometric, financial, children’s data, etc.)
- [ ] Dual-use or military-applicable technology
- [ ] Safety-critical systems (medical device, aviation, automotive, etc.)
- [ ] High-impact algorithmic decision-making (credit, hiring, criminal justice, etc.)
- [ ] None of the above (pure docs, tests, CI, formatting, etc.)

2. Estimated risk level (your honest assessment)
- [ ] Low – no ethical or regulatory impact
- [ ] Medium – possible fairness/privacy concerns
- [ ] High – potential for serious harm or legal non-compliance

3. Brief description of any ethical/regulatory impact (or write “None”)

**Pull Request Ethics, Security & Compliance Checklist**
*(Mandatory for all pull requests. This helps you develop professional habits required in industry and academia.)*

1. Nature of the contribution (select all that apply)
- [ ] Purely non-functional changes (documentation, formatting, tests, CI/CD, refactoring without behavioral change)
- [ ] Introduction or modification of cryptographic functions or security-critical code
- [ ] Collection, storage, transmission, or processing of personal data (PII, health data, biometric data, location, etc.)
- [ ] Use or processing of data belonging to children under 13 (or reasonably likely to include such data)
- [ ] Implementation or modification of AI/ML models (training, fine-tuning, inference, prompt engineering)
- [ ] Code interacting with external networks, APIs, or third-party services

2. Security & responsible practice assessment
- [ ] No security, privacy, or ethical implications identified
- [ ] Potential security or privacy implications present (e.g., input validation, error handling, data exposure)
- [ ] High-risk implications (potential for unauthorized access, data leakage, bias, or legal non-compliance)

3. Relevant laws, regulations, and frameworks considered (list all that may apply, or if none, refer to content in D2L Ethics module)
Examples:
- Australian Privacy Act 1988 (Cth) & Privacy Amendment (Notifiable Data Breaches) Act 2017
- GDPR (EU), CCPA/CPRA (California), COPPA (US children’s privacy)
- University Human Research Ethics requirements (HREC/NHRMC)
- NIST Cybersecurity Framework / OWASP Top 10 / ASVS
- ISO/IEC 27001, NIST AI Risk Management Framework (AI RMF)
- Export controls (ITAR, EAR, Australian Defence Export Controls)
>

4. Relevant regulations / standards considered (e.g., EU AI Act, GDPR, HIPAA, NIST AI RMF, export controls, etc.)
List them or write “N/A”

4. Security and responsible engineering measures implemented (select and describe)
- [ ] Yes — specify below (e.g., input sanitization, prepared statements, least-privilege access, data minimization, anonymization, secure defaults, dependency scanning, bias audit, consent mechanism, etc.)
- [ ] Partially implemented — further review recommended
- [ ] No — measures appear necessary
- [ ] Not applicable
>

5. Have mitigation measures been implemented (bias testing, data minimization, consent flows, etc.)?
- [ ] Yes → describe below
- [ ] No
- [ ] Not applicable

5. Additional notes (optional)
Any references to secure coding guidelines followed (e.g., ISO27001, OWASP Secure Coding Practices, university security standards), vulnerability scans performed, or ethical review status.
>

Thank you! The ethics gate will evaluate your answers automatically.
By submitting this pull request, I confirm I have considered the security, privacy, and ethical implications of my contribution in accordance with university policy and applicable legal and professional standards.

Thank you for helping maintain a secure and responsible codebase.
108 changes: 2 additions & 106 deletions .github/workflows/ethics-gate.yaml
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
on:
pull_request_target:
types: [opened, reopened, synchronize]
issue_comment:
types: [created]

permissions:
contents: read # needed for checkout
pull-requests: write # needed for commenting & reviews (gh) when running in pull_request_target
checks: write # needed to create check runs
pull-requests: write # needed for posting comments

jobs:
# Job that posts the questionnaire (runs in the trusted pull_request_target context).
post-questionnaire:
if: github.event_name == 'pull_request_target' && github.event.pull_request.draft == false
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
steps:
- name: Checkout base repo (safe; do NOT checkout PR head here)
Expand Down Expand Up @@ -47,103 +43,3 @@ jobs:
fi
gh pr comment ${{ github.event.pull_request.number }} --body-file .github/ETHICS_QUESTIONNAIRE.MD
echo "Posted ethics questionnaire to PR #${{ github.event.pull_request.number }}."

# Ethics engine: collects comments, runs evaluation, posts a check, and requests changes for HIGH risk.
# This job runs in the trusted context for pull_request_target and also on issue_comment (untrusted).
# For untrusted issue_comment runs, write actions (requesting changes) may be skipped if permissions are restricted.
ethics-engine:
runs-on: ubuntu-latest
needs: post-questionnaire
steps:
- name: Checkout base repo (we run parser from base repo)
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.base.sha || github.ref }}
fetch-depth: 0

- name: Authenticate gh CLI with GITHUB_TOKEN
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | gh auth login --with-token

- name: Determine PR number
id: prnumber
run: |
# Determine PR number whether triggered by pull_request_target or issue_comment
PR_NUMBER=$(jq -r 'if .pull_request then .pull_request.number elif .issue then .issue.number else empty end' "$GITHUB_EVENT_PATH")
if [[ -z "$PR_NUMBER" ]]; then
echo "No PR number found in event payload; exiting."
echo "risk=UNKNOWN" >> $GITHUB_OUTPUT
exit 0
fi
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT

- name: Collect comments
id: collect
run: |
PR=${{ steps.prnumber.outputs.pr_number }}
# Gather all PR comments into a single string (robust to empty)
ANSWERS=$(gh pr view "$PR" --json comments --jq '[.comments[].body] | join("\n\n")' 2>/dev/null || true)
echo "$ANSWERS" > answers.txt
# Expose the answers (trim to avoid huge output)
echo "answers=$(echo "$ANSWERS" | head -c 32768 | sed -e 's/"/'"'"'"/g')" >> $GITHUB_OUTPUT

- name: Run ethics parser & evaluator (safe runs code from base repo)
id: run_engine
env:
PR_NUMBER: ${{ steps.prnumber.outputs.pr_number }}
run: |
# Ensure parser exists
if [[ ! -f .github/workflows/parse_and_evaluate.py ]]; then
echo "Parser .github/workflows/parse_and_evaluate.py not found in base repo; aborting."
echo "RISK_LEVEL=UNKNOWN" > result.txt
else
python3 .github/workflows/parse_and_evaluate.py "$(cat answers.txt)" > result.txt || true
fi
cat result.txt
# Extract RISK_LEVEL=XYZ from result.txt if present
RISK=$(grep -m1 '^RISK_LEVEL=' result.txt | cut -d= -f2 || echo "LOW")
echo "risk=$RISK" >> $GITHUB_OUTPUT

- name: Create/update "Ethics Review" check run
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const risk = "${{ steps.run_engine.outputs.risk }}".trim();
const conclusions = {
"LOW": "success",
"MEDIUM": "action_required",
"HIGH": "failure"
};
const conclusion = conclusions[risk] || "failure";
const head_sha = (context.payload.pull_request && context.payload.pull_request.head && context.payload.pull_request.head.sha) || (context.payload.issue && context.payload.issue.pull_request && context.payload.issue.number ? undefined : undefined) || github.event.pull_request?.head?.sha;
await github.rest.checks.create({
owner: context.repo.owner,
repo: context.repo.repo,
name: "Ethics Review",
head_sha: head_sha || context.sha,
status: "completed",
conclusion,
output: {
title: risk === "LOW" ? "Ethics cleared" : `Ethics review: ${risk}`,
summary: risk === "LOW" ? "Low risk – automatically approved" : `Risk level ${risk} – review required`
}
});

- name: Request changes on HIGH risk (trusted-only; skip on untrusted events)
if: steps.run_engine.outputs.risk == 'HIGH'
run: |
PR=${{ steps.prnumber.outputs.pr_number }}
# Only attempt to request changes when running in pull_request_target context (trusted).
if [[ "${GITHUB_EVENT_NAME}" != "pull_request_target" ]]; then
echo "Not in pull_request_target context; skipping request-changes (insufficient permissions for fork PRs)."
exit 0
fi
# Request changes using gh (GITHUB_TOKEN from pull_request_target has write rights)
gh pr review "$PR" --request-changes -b "@ethics-team Required manual review for high-risk change"
echo "Requested changes on PR #$PR due to HIGH risk."

- name: Final status message
run: |
echo "Ethics engine completed. Risk level: ${{ steps.run_engine.outputs.risk }}"
echo "Ethics engine completed. Risk level: ${{ steps.run_engine.outputs.risk }}"
38 changes: 0 additions & 38 deletions .github/workflows/redeengine.py

This file was deleted.

Binary file modified README.md
Binary file not shown.
19 changes: 14 additions & 5 deletions asset-scanner/file_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,21 @@
from scan_media import extract_text_from_file

def find_files(directory, exts=None):
exts = exts or []
"""Find all matching files in a directory, optionally filtered by extensions."""
exts = exts or [] # List of extensions to filter files
matches = []
for dirpath, _, filenames in os.walk(directory):
for fn in filenames:
if not exts or any(fn.lower().endswith(e) for e in exts):
matches.append(os.path.join(dirpath, fn))

try:
for dirpath, _, filenames in os.walk(directory): # Traverse directory recursively
for fn in filenames:
# Skip files not matching the desired extensions
if not exts or any(fn.lower().endswith(e.lower()) for e in exts):
matches.append(os.path.join(dirpath, fn))
except PermissionError:
print(f"[!] Permission denied for directory: {directory}. Skipping...")
# Continue to the next folder
pass

return matches

def read_file(path):
Expand Down
Empty file removed asset-scanner/scan_report.json
Empty file.
Loading