-
Notifications
You must be signed in to change notification settings - Fork 408
feat(security+ai): goal-oriented agent + hardening de segurança (audit 2026-04-17) #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
78a0115
fix(security): corrigir múltiplas vulnerabilidades críticas identific…
thaleslaray cb3d9f3
feat(ops): melhorias de performance, acessibilidade, CI/CD e observab…
thaleslaray 4a74230
fix: timing-safe Evolution, lint zero-warning, testes input-filter/ou…
thaleslaray f438acf
fix: corrigir regressões e falsos positivos pós-audit
thaleslaray de56b63
feat(security+ai): goal-oriented agent, audit fixes e hardening de se…
thaleslaray a9d4833
fix(security): correções phase-2 — injection, SSRF, cross-tenant
thaleslaray File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| { | ||
| "extends": ["@commitlint/config-conventional"], | ||
| "rules": { | ||
| "type-enum": [ | ||
| 2, | ||
| "always", | ||
| [ | ||
| "feat", | ||
| "fix", | ||
| "docs", | ||
| "style", | ||
| "refactor", | ||
| "perf", | ||
| "test", | ||
| "chore", | ||
| "ci", | ||
| "revert" | ||
| ] | ||
| ], | ||
| "type-case": [2, "always", "lowercase"], | ||
| "type-empty": [2, "never"], | ||
| "subject-empty": [2, "never"], | ||
| "subject-full-stop": [2, "never", "."], | ||
| "subject-case": [2, "never", ["start-case", "pascal-case", "upper-case"]], | ||
| "header-max-length": [2, "always", 100] | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,141 @@ | ||
| # CI — NossoCRM | ||
| # | ||
| # Jobs: | ||
| # check — lint + typecheck + tests (runs on every PR and push to main/feature branches) | ||
| # build — Next.js production build (runs only on push to main) | ||
| # | ||
| # Cache strategy: | ||
| # - pnpm store: keyed on pnpm-lock.yaml hash via actions/setup-node cache: "pnpm" | ||
| # - .next/cache: keyed on source hash, restores on prefix match | ||
| # | ||
| # Security: no untrusted event inputs are interpolated into run: commands. | ||
|
|
||
| name: CI | ||
|
|
||
| on: | ||
| push: | ||
| branches: | ||
| - main | ||
| - "feature/**" | ||
| - "fix/**" | ||
| pull_request: | ||
| branches: | ||
| - main | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| env: | ||
| NODE_VERSION: "20" | ||
| PNPM_VERSION: "9" | ||
|
|
||
| jobs: | ||
| # ─── commitlint ──────────────────────────────────────────────────────────── | ||
| # Validates commit messages follow conventional commits format | ||
| # Runs only on PRs to catch format issues before merge | ||
| commitlint: | ||
| name: Validate Conventional Commits | ||
| runs-on: ubuntu-latest | ||
| if: github.event_name == 'pull_request' | ||
|
|
||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: ${{ env.NODE_VERSION }} | ||
|
|
||
| - name: Install commitlint | ||
| run: npm install --save-dev @commitlint/cli @commitlint/config-conventional --legacy-peer-deps | ||
|
|
||
| - name: Validate commits | ||
| run: | | ||
| npx commitlint \ | ||
| --from ${{ github.event.pull_request.base.sha }} \ | ||
| --to ${{ github.event.pull_request.head.sha }} | ||
|
|
||
| # ─── check ──────────────────────────────────────────────────────────────── | ||
| # Runs precheck:fast: ESLint (--max-warnings 0) + tsc --noEmit + vitest run | ||
| # Fast path — no Next.js build required. Runs on all triggering events. | ||
| check: | ||
| name: Lint / Typecheck / Tests | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 10 | ||
|
|
||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Setup pnpm | ||
| uses: pnpm/action-setup@v4 | ||
| with: | ||
| version: ${{ env.PNPM_VERSION }} | ||
|
|
||
| - name: Setup Node.js ${{ env.NODE_VERSION }} | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: ${{ env.NODE_VERSION }} | ||
| cache: "pnpm" | ||
|
|
||
| - name: Install dependencies | ||
| run: pnpm install --frozen-lockfile | ||
|
|
||
| - name: Lint (ESLint — zero warnings) | ||
| run: pnpm lint | ||
|
|
||
| - name: Typecheck (tsc --noEmit) | ||
| run: pnpm typecheck | ||
|
|
||
| - name: Tests (Vitest) | ||
| run: pnpm test:run | ||
|
|
||
| # ─── build ──────────────────────────────────────────────────────────────── | ||
| # Full Next.js production build. Runs only on pushes to main. | ||
| # Depends on check passing to avoid wasting build minutes on broken code. | ||
| build: | ||
| name: Build (Next.js) | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 15 | ||
| needs: check | ||
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | ||
|
|
||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Setup pnpm | ||
| uses: pnpm/action-setup@v4 | ||
| with: | ||
| version: ${{ env.PNPM_VERSION }} | ||
|
|
||
| - name: Setup Node.js ${{ env.NODE_VERSION }} | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: ${{ env.NODE_VERSION }} | ||
| cache: "pnpm" | ||
|
|
||
| - name: Restore Next.js build cache | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: | | ||
| ${{ github.workspace }}/.next/cache | ||
| key: ${{ runner.os }}-nextjs-${{ hashFiles('**/pnpm-lock.yaml') }}-${{ hashFiles('**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.css') }} | ||
| restore-keys: | | ||
| ${{ runner.os }}-nextjs-${{ hashFiles('**/pnpm-lock.yaml') }}- | ||
| ${{ runner.os }}-nextjs- | ||
|
|
||
| - name: Install dependencies | ||
| run: pnpm install --frozen-lockfile | ||
|
|
||
| - name: Build | ||
| run: pnpm build | ||
| env: | ||
| # Next.js build requires these to be present even if not used at runtime. | ||
| # Real values come from Vercel project settings — these are build-time only. | ||
| NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL }} | ||
| NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY }} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| # Preview — NossoCRM | ||
| # | ||
| # Triggers a Vercel Preview deployment on every PR. | ||
| # The deployment URL is posted as a PR comment via Vercel's GitHub integration. | ||
| # | ||
| # Prerequisites (set in repo Settings → Secrets and variables → Actions): | ||
| # VERCEL_TOKEN — personal access token from vercel.com/account/tokens | ||
| # VERCEL_ORG_ID — from .vercel/project.json or `vercel env pull` | ||
| # VERCEL_PROJECT_ID — from .vercel/project.json or `vercel env pull` | ||
| # | ||
| # This job does NOT run the build itself — Vercel handles the build on its | ||
| # infrastructure using the same Next.js config. The CI check job (ci.yml) | ||
| # is the quality gate; preview deploy runs in parallel to save time. | ||
| # | ||
| # Security: no untrusted event inputs are interpolated into run: commands. | ||
|
|
||
| name: Preview Deploy | ||
|
|
||
| on: | ||
| pull_request: | ||
| branches: | ||
| - main | ||
|
|
||
| concurrency: | ||
| group: preview-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| deploy-preview: | ||
| name: Deploy Preview to Vercel | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 10 | ||
| permissions: | ||
| pull-requests: write | ||
|
|
||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Deploy to Vercel (Preview) | ||
| id: deploy | ||
| uses: amondnet/vercel-action@v25 | ||
| with: | ||
| vercel-token: ${{ secrets.VERCEL_TOKEN }} | ||
| vercel-org-id: ${{ secrets.VERCEL_ORG_ID }} | ||
| vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }} | ||
| # Do not promote to production on this workflow | ||
| vercel-args: "--no-wait" | ||
| github-comment: true | ||
| github-token: ${{ secrets.GITHUB_TOKEN }} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| # Release — NossoCRM | ||
| # | ||
| # Triggered when a semantic version tag (vX.Y.Z) is pushed to main branch. | ||
| # Creates a GitHub Release with auto-generated release notes from merged PRs. | ||
| # | ||
| # Usage: | ||
| # npm run release:prepare # Analyze commits and suggest version | ||
| # npm run release:draft # Preview changelog | ||
| # npm run release:tag # Create tag and push | ||
| # git push origin main | ||
| # git push origin vX.Y.Z # This triggers this workflow | ||
|
|
||
| name: Release | ||
|
|
||
| on: | ||
| push: | ||
| tags: | ||
| - "v*.*.*" | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: false | ||
|
|
||
| jobs: | ||
| # ─── release ────────────────────────────────────────────────────────────── | ||
| # Create GitHub Release from pushed semantic version tag | ||
| release: | ||
| name: Create Release | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: write | ||
|
|
||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 # Fetch full history for changelog generation | ||
|
|
||
| - name: Extract version from tag | ||
| id: version | ||
| env: | ||
| REF_NAME: ${{ github.ref_name }} | ||
| run: | | ||
| TAG="${REF_NAME}" | ||
| VERSION="${TAG#v}" | ||
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | ||
| echo "tag=${TAG}" >> $GITHUB_OUTPUT | ||
| echo "Release version: ${VERSION}" | ||
|
|
||
| - name: Get previous release | ||
| id: prev_release | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| LATEST=$(gh release list --limit 1 --json tagName --jq -r '.[] | .tagName' 2>/dev/null || echo "") | ||
| if [ -z "$LATEST" ]; then | ||
| PREV_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") | ||
| else | ||
| PREV_TAG="${LATEST}" | ||
| fi | ||
| echo "previous_tag=${PREV_TAG}" >> $GITHUB_OUTPUT | ||
|
|
||
| - name: Extract changelog for version | ||
| id: changelog | ||
| env: | ||
| VERSION: ${{ steps.version.outputs.version }} | ||
| run: | | ||
| if [ -f "CHANGELOG.md" ]; then | ||
| # Extract section from ## [VERSION] to next ## [ | ||
| # Using a safe shell command to avoid injection | ||
| awk "/^## \[${VERSION}\]/,/^## \[/" CHANGELOG.md | head -n -1 > /tmp/changelog.txt | ||
| if [ -s /tmp/changelog.txt ]; then | ||
| # Convert to GitHub Actions multiline format | ||
| { | ||
| echo 'NOTES<<EOF' | ||
| cat /tmp/changelog.txt | ||
| echo 'EOF' | ||
| } >> $GITHUB_ENV | ||
| fi | ||
| fi | ||
|
|
||
| - name: Create GitHub Release | ||
| uses: softprops/action-gh-release@v1 | ||
| with: | ||
| tag_name: ${{ steps.version.outputs.tag }} | ||
| name: Release ${{ steps.version.outputs.version }} | ||
| body: | | ||
| ${{ env.NOTES }} | ||
|
|
||
| --- | ||
|
|
||
| **Full Diff**: https://github.com/${{ github.repository }}/compare/${{ steps.prev_release.outputs.previous_tag }}...${{ steps.version.outputs.tag }} | ||
| draft: false | ||
| prerelease: false | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
gh CLI --jq flag syntax for extracting raw values from --json output💡 Result:
The syntax for the gh CLI --jq flag to extract raw values from --json output is: gh --json <field1,field2,...> --jq '' Key points: - --json must be used first with a comma-separated list of fields (e.g., number,title,author). Run gh --json without fields to list available fields. - --jq follows, taking a string argument in standard jq query syntax (quoted with single quotes for shell safety). - The --jq expression processes the JSON array/object from --json and outputs matching raw values, without quotes for strings when possible. - No external jq tool is needed; gh has built-in support. - Output is pretty-printed in terminals. Examples: 1. Extract author logins as raw strings: gh pr list --json author --jq '.[].author.login' Output: monalisa codercat cli-maintainer 2. Complex filtering (issues with labels, first 3): gh issue list --json number,title,labels --jq 'map(select((.labels | length) > 0)) | map(.labels = (.labels | map(.name))) | .[:3]' For gh api, --jq works similarly on the API response: gh api repos/{owner}/{repo}/issues --jq '.[].title' To get raw values without formatting/quoting, use jq expressions like .field or .[].field that output primitives directly.
Citations:
gh --jq -r '…'is malformed — the step always falls back togit describe.gh release list --jqtakes a single jq expression as its argument. The-rflag does not exist for gh's built-in jq—it is a standalone jq tool flag. As written, gh receives--jq -r(treating-ras the jq expression) and.[] | .tagNameas extraneous positional arguments, which fails. Because of2>/dev/null || echo "",LATESTis always empty and the fallbackgit describe --tags --abbrev=0is the only path actually used—so GitHub Releases is never consulted.🔧 Proposed fix
📝 Committable suggestion
🤖 Prompt for AI Agents