Skip to content
Open
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
28 changes: 28 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
## Goal
Describe in one sentence what this PR delivers.

## Changes
- Added/updated:
- Added/updated:
- Added/updated:

## Testing
List the commands you ran and the observed results.

```bash
# paste commands here
```

Observed output/results:
-
-
-

## Artifacts & Screenshots
- Submission file: `submissions/labN.md`
- Other artifacts:
- Screenshots:

- [ ] Title is clear (`feat(labN): <topic>` style)
- [ ] No secrets/large temp files committed
- [ ] Submission file at `submissions/labN.md` exists
40 changes: 40 additions & 0 deletions .github/workflows/lab1-smoke.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Lab 1 Smoke Test

on:
pull_request:
branches:
- main

permissions:
contents: read

jobs:
smoke-test:
runs-on: ubuntu-latest

steps:
- name: Pull Juice Shop image
run: docker pull bkimminich/juice-shop:v20.0.0

- name: Start Juice Shop
run: |
docker run -d \
--name juice-shop \
-p 3000:3000 \
bkimminich/juice-shop:v20.0.0

- name: Wait for application
run: |
for i in $(seq 1 30); do
curl --silent --fail http://localhost:3000/rest/admin/application-version >/dev/null && exit 0
sleep 2
done
exit 1

- name: Verify homepage returns HTTP 200
run: |
test "$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/)" = "200"

- name: Show HTTP status code
run: |
curl -is http://localhost:3000/ | head -n1
11 changes: 11 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.30.1
hooks:
- id: gitleaks

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: detect-private-key
- id: check-added-large-files
110 changes: 110 additions & 0 deletions submissions/lab3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Lab 3 - Submission

## Task 1: SSH Commit Signing

### Local configuration
- `git config --global gpg.format` -> `ssh`
- `git config --global user.signingkey` -> `/Users/rom.m.ivanov/.ssh/id_ed25519.pub`
- `git config --global commit.gpgsign` -> `true`

### Local verification
Output of `git log --show-signature -1`:
```
commit 61b2853e6f42d1b92483dd10cccaabb5834545e6
Good "git" signature for ro.ivanov@innopolis.university with ED25519 key SHA256:[REDACTED]
Author: eraegar <romaxim2006@gmail.com>
Date: Wed Jun 17 23:45:54 2026 +0300

feat(lab3): SSH signing, gitleaks hooks, and history rewrite notes
```

### GitHub verification
- Direct link to your most recent commit on GitHub: [add after push]
- Screenshot of the Verified badge: [attach in PR or link after push]

### One-paragraph reflection (2-3 sentences)
In a real team, an unsigned or forged-author commit could let someone deny responsibility for a change or impersonate another developer when introducing malicious code. A visible Verified badge does not prove the code is safe, but it makes authorship tampering much easier to detect and strengthens the audit trail for reviews and incident response.

## Task 2: Pre-commit + gitleaks

### `.pre-commit-config.yaml` (paste the full content)
```yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.30.1
hooks:
- id: gitleaks

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: detect-private-key
- id: check-added-large-files
```

### `pre-commit install` output
```
pre-commit installed at .git/hooks/pre-commit
```

### The blocked commit
Output of the `git commit` that gitleaks blocked:
```
Detect hardcoded secrets.................................................Failed
- hook id: gitleaks
- exit code: 1

│╲
│ ○
○ ░
░ gitleaks

Finding: GH_PAT=REDACTED
Secret: REDACTED
RuleID: github-pat
Entropy: 4.143943
File: submissions/leak-attempt.txt
Line: 2
Fingerprint: submissions/leak-attempt.txt:github-pat:2

11:17PM INF 0 commits scanned.
11:17PM INF scanned ~101 bytes (101 bytes) in 22.4ms
11:17PM WRN leaks found: 1

detect private key.......................................................Passed
check for added large files..............................................Passed
```

### Tune-out exercise
1. **Inline allowlist** - An inline allowlist in `.gitleaks.toml` is acceptable when a specific example value is known, intentional, and tightly scoped, such as a canonical documentation token that is not real and cannot be abused. The advantage is precision: the rule still protects the rest of the repository without suppressing unrelated findings.
2. **Path exclusion** - Excluding a whole path such as `docs/` is riskier because it creates a blind spot where real secrets can later be committed unnoticed. It may be tempting for noisy documentation folders, but it trades convenience for a broader loss of coverage and should be used very carefully.

## Bonus: History Rewrite

### Before
```
ba9c76e (HEAD -> main) docs: add usage notes
0afb204 feat: empty log
0cde15a feat: add config
8a8d948 init
```
Output of `git log -p | grep -c 'ghp_'`: **2**

### After
```
5d18498 (HEAD -> main) docs: add usage notes
4d0f9ed feat: empty log
0373b55 feat: add config
eb63517 init
```
Output of `git log -p | grep -c 'ghp_'`: **0**
Output of `git log -p | grep -c 'REDACTED'`: **2**

### The two-step pattern in real life
1. `git filter-repo --replace-text replacements.txt` - rewrite locally
2. Rotate or revoke the exposed secret and then force-push the rewritten history to the remote. Rewriting history removes the value from Git, but remediation still requires treating the leaked credential as compromised.

### Two real-world gotchas you discovered (2 sentences each)
1. `git filter-repo` changes commit IDs, so every rewritten commit becomes a different object and any collaborators must resync carefully afterward. In a real shared repository, this makes communication and force-push coordination part of the incident response, not an optional cleanup detail.
2. Removing the secret from current files is not enough if it still exists in older commits. The exercise shows why prevention with hooks matters: once a secret enters history, cleanup is slower, riskier, and easier to get wrong.