mirror of
https://github.com/moonD4rk/HackBrowserData.git
synced 2026-05-19 18:58:03 +02:00
chore: update CI, golangci-lint, and CLAUDE.md (#511)
* chore: update CI, golangci-lint, and CLAUDE.md * fix: resolve CI failures on Windows test and lint * fix: resolve Windows test path and main.go line length lint issues * fix: auto-format log/ with gofumpt, exclude pre-refactoring lint issues * fix: resolve remaining lint issues, remove unnecessary exclusions * fix: remove invalid G117 gosec rule, use text exclusion for secret pattern * fix: align CI golangci-lint version with local (v2.4 -> v2.10)
This commit is contained in:
@@ -7,6 +7,9 @@ on:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build on ${{ matrix.os }}
|
||||
@@ -14,38 +17,12 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
goVer: ["1.20.x"]
|
||||
|
||||
steps:
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Go ${{ matrix.goVer }}
|
||||
uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{ matrix.goVer }}
|
||||
cache: false
|
||||
id: go
|
||||
|
||||
- name: cache go modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/go/pkg/mod
|
||||
~/.cache/go-build
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-go-
|
||||
|
||||
- name: Format Check
|
||||
if: matrix.os != 'windows-latest'
|
||||
run: |
|
||||
diff -u <(echo -n) <(gofmt -d .)
|
||||
|
||||
- name: Get dependencies
|
||||
run: |
|
||||
go mod tidy
|
||||
go mod download
|
||||
go-version-file: go.mod
|
||||
|
||||
- name: Build
|
||||
run: go build -v ./...
|
||||
|
||||
+10
-14
@@ -5,31 +5,27 @@ on:
|
||||
- main
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Set Golang
|
||||
uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: "1.20.x"
|
||||
cache: false
|
||||
go-version-file: go.mod
|
||||
|
||||
- name: Check spelling with custom config file
|
||||
- name: Check spelling
|
||||
uses: crate-ci/typos@master
|
||||
with:
|
||||
config: ./.typos.toml
|
||||
|
||||
- name: Get dependencies
|
||||
run: |
|
||||
go mod tidy
|
||||
go mod download
|
||||
|
||||
- name: Lint
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v8
|
||||
with:
|
||||
version: v2.4.0
|
||||
version: v2.10
|
||||
|
||||
@@ -11,16 +11,16 @@ jobs:
|
||||
goreleaser:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.20.x'
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
|
||||
+23
-31
@@ -1,51 +1,43 @@
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test (${{ matrix.os }})
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [ "1.20.x" ]
|
||||
platform: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Install Go
|
||||
if: success()
|
||||
uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
go-version-file: go.mod
|
||||
|
||||
- name: Run tests
|
||||
run: go test -v ./... -covermode=count
|
||||
if: matrix.os == 'windows-latest'
|
||||
run: go test -v ./...
|
||||
|
||||
coverage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install Go
|
||||
if: success()
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.20.x"
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
- name: Calc coverage
|
||||
run: |
|
||||
go test -v ./... -covermode=count -coverprofile=coverage.out
|
||||
- name: Run tests with coverage
|
||||
if: matrix.os != 'windows-latest'
|
||||
run: go test -v -coverprofile=coverage.out ./...
|
||||
|
||||
- name: Convert coverage.out to coverage.lcov
|
||||
uses: jandelgado/gcov2lcov-action@v1
|
||||
- name: Coveralls
|
||||
uses: coverallsapp/github-action@v2
|
||||
- name: Upload coverage
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
github-token: ${{ secrets.github_token }}
|
||||
path-to-lcov: coverage.lcov
|
||||
use_oidc: true
|
||||
files: ./coverage.out
|
||||
fail_ci_if_error: false
|
||||
flags: unittests
|
||||
|
||||
+190
-246
@@ -1,272 +1,216 @@
|
||||
# golangci-lint configuration
|
||||
# Compatible with golangci-lint v2.4+ and Go 1.20
|
||||
# This is a best practice starter configuration that can be gradually enhanced
|
||||
# golangci-lint v2 configuration
|
||||
# Compatible with Go 1.20
|
||||
version: "2"
|
||||
|
||||
run:
|
||||
# Go version - fixed to 1.20
|
||||
go: "1.20"
|
||||
# Timeout setting
|
||||
timeout: "5m"
|
||||
# Allow parallel runners
|
||||
allow-parallel-runners: true
|
||||
# Module download mode
|
||||
modules-download-mode: "mod"
|
||||
|
||||
# Code formatters configuration
|
||||
formatters:
|
||||
enable:
|
||||
- gofmt # Go official formatter
|
||||
- goimports # Automatic import management
|
||||
- gci # Import grouping and sorting
|
||||
|
||||
settings:
|
||||
gofmt:
|
||||
# Simplify code
|
||||
simplify: true
|
||||
|
||||
goimports:
|
||||
# Local package prefix (must be array in v2)
|
||||
local-prefixes:
|
||||
- github.com/moond4rk/hackbrowserdata
|
||||
|
||||
gci:
|
||||
# Import section order
|
||||
sections:
|
||||
- standard # Standard library
|
||||
- default # Third-party libraries
|
||||
- prefix(github.com/moond4rk/hackbrowserdata) # Local packages
|
||||
|
||||
# Linter configuration
|
||||
linters:
|
||||
# Use standard linters as base
|
||||
default: standard
|
||||
|
||||
# Additional enabled linters (best practices recommended)
|
||||
default: none
|
||||
enable:
|
||||
# Error checking
|
||||
- errcheck # Check unhandled errors
|
||||
- errorlint # Improve error handling
|
||||
# Default tier
|
||||
- errcheck
|
||||
- govet
|
||||
- staticcheck
|
||||
- ineffassign
|
||||
- unused
|
||||
|
||||
# Bug detection
|
||||
- errorlint
|
||||
- gosec
|
||||
- sqlclosecheck
|
||||
|
||||
# Code quality
|
||||
- ineffassign # Detect ineffective assignments
|
||||
- revive # Code quality checks
|
||||
- misspell # Spell checking
|
||||
- unconvert # Detect unnecessary type conversions
|
||||
- depguard
|
||||
- dogsled
|
||||
- dupl
|
||||
- errname
|
||||
- funlen
|
||||
- gocheckcompilerdirectives
|
||||
- gochecknoinits
|
||||
- goconst
|
||||
- gocritic
|
||||
- godox
|
||||
- goprintffuncname
|
||||
- lll
|
||||
- misspell
|
||||
- nakedret
|
||||
- revive
|
||||
- testifylint
|
||||
- unconvert
|
||||
- unparam
|
||||
- usestdlibvars
|
||||
- whitespace
|
||||
|
||||
# Security related
|
||||
- gosec # Security vulnerability checks
|
||||
# Complexity
|
||||
- gocognit
|
||||
|
||||
# Performance related
|
||||
- prealloc # Slice preallocation optimization
|
||||
# Note: copyloopvar, intrange, modernize, perfsprint require Go 1.22+
|
||||
# They will be enabled when Go version constraint is lifted
|
||||
|
||||
# Code standards
|
||||
- whitespace # Whitespace checks
|
||||
|
||||
# Best practices
|
||||
- gocritic # Comprehensive code analysis
|
||||
- goprintffuncname # Printf function naming checks
|
||||
|
||||
# Dependency management
|
||||
- depguard # Package dependency control
|
||||
- gomodguard # Go module dependency control
|
||||
|
||||
# Code complexity (optional for initial setup)
|
||||
- funlen # Function length checks
|
||||
- goconst # Magic number checks
|
||||
|
||||
# Explicitly disabled linters (to avoid false positives and noise)
|
||||
disable:
|
||||
- exhaustruct # Struct field completeness check (too strict)
|
||||
- wrapcheck # Error wrapping check (project specific)
|
||||
- testpackage # Test package separation (not conventional)
|
||||
- paralleltest # Parallel test check (not always needed)
|
||||
- nlreturn # Newline before return (too strict)
|
||||
- wsl # Whitespace rules (too strict)
|
||||
- gochecknoglobals # No global variables (sometimes needed)
|
||||
- gochecknoinits # No init functions (sometimes needed)
|
||||
- exhaustive # Enum completeness (too strict initially)
|
||||
- unused # Temporarily disabled for gradual cleanup
|
||||
|
||||
# Exclusion configuration
|
||||
exclusions:
|
||||
# Paths to exclude
|
||||
paths:
|
||||
- vendor
|
||||
- third_party
|
||||
- testdata
|
||||
- ".*\\.pb\\.go$"
|
||||
- ".*\\.gen\\.go$"
|
||||
|
||||
# Use default exclusion presets
|
||||
presets:
|
||||
- comments
|
||||
- common-false-positives
|
||||
- legacy
|
||||
- std-error-handling
|
||||
|
||||
# Exclusion rules
|
||||
rules:
|
||||
# Test file exclusions
|
||||
- path: '_test\.go'
|
||||
linters:
|
||||
- dupl
|
||||
- funlen
|
||||
- goconst
|
||||
- gosec
|
||||
- errcheck
|
||||
|
||||
# Generated file exclusions
|
||||
- path: '\.pb\.go$'
|
||||
linters:
|
||||
- all
|
||||
|
||||
# Vendor directory exclusions
|
||||
- path: "vendor"
|
||||
linters:
|
||||
- all
|
||||
|
||||
# Defer statement exclusions
|
||||
- source: "defer"
|
||||
linters:
|
||||
- errcheck
|
||||
|
||||
# SQL query exclusions
|
||||
- text: "SELECT"
|
||||
linters:
|
||||
- gosec
|
||||
|
||||
# Package comment exclusions
|
||||
- text: "should have a package comment"
|
||||
linters:
|
||||
- staticcheck
|
||||
- revive
|
||||
|
||||
# Types package exclusions
|
||||
- path: "types/types.go"
|
||||
linters:
|
||||
- revive
|
||||
|
||||
# Unused code exclusions (temporary)
|
||||
- text: "is unused"
|
||||
linters:
|
||||
- unused
|
||||
- staticcheck
|
||||
|
||||
# Linter specific settings
|
||||
settings:
|
||||
# Error check settings
|
||||
errcheck:
|
||||
# Check type assertion errors
|
||||
check-type-assertions: true
|
||||
# Don't check blank identifier
|
||||
check-blank: false
|
||||
# Excluded functions - expanded list to reduce noise
|
||||
exclude-functions:
|
||||
- "os.Remove"
|
||||
- "os.RemoveAll"
|
||||
- "io.Copy(os.Stdout)"
|
||||
- "(*database/sql.DB).Close"
|
||||
- "(*database/sql.Rows).Close"
|
||||
- "(*github.com/syndtr/goleveldb/leveldb.DB).Close"
|
||||
- "defer"
|
||||
- "(net/http.ResponseWriter).Write"
|
||||
|
||||
# Security check settings
|
||||
gosec:
|
||||
# Excluded rules (adjust based on project needs)
|
||||
excludes:
|
||||
- G101 # Hardcoded credentials - too many false positives
|
||||
- G104 # Error checking (handled by errcheck)
|
||||
- G304 # File path traversal (needed for project features)
|
||||
- G306 # Poor file permissions (test files)
|
||||
- G401 # Weak cryptographic algorithm (needed for compatibility)
|
||||
- G405 # Weak cryptographic algorithm
|
||||
- G501 # Import crypto/md5 (needed for compatibility)
|
||||
- G502 # Import crypto/des (needed for compatibility)
|
||||
- G505 # Import crypto/sha1 (needed for compatibility)
|
||||
|
||||
# Go vet settings
|
||||
govet:
|
||||
enable-all: true
|
||||
disable:
|
||||
- fieldalignment # Field alignment optimization (premature optimization)
|
||||
- shadow # Variable shadowing (sometimes intentional)
|
||||
|
||||
# Static check settings
|
||||
staticcheck:
|
||||
# Check all except the ones we exclude
|
||||
checks:
|
||||
[
|
||||
"all",
|
||||
"-ST1000",
|
||||
"-ST1003",
|
||||
"-ST1016",
|
||||
"-ST1020",
|
||||
"-ST1021",
|
||||
"-ST1022",
|
||||
]
|
||||
|
||||
# Revive settings
|
||||
revive:
|
||||
severity: warning
|
||||
depguard:
|
||||
rules:
|
||||
- name: unused-parameter
|
||||
disabled: true # Interface implementations may not use all parameters
|
||||
- name: var-naming
|
||||
disabled: true # Too many false positives with types package
|
||||
- name: package-comments
|
||||
disabled: true # Package comments are not mandatory
|
||||
- name: exported
|
||||
disabled: true # Not all exported types need comments initially
|
||||
|
||||
# Function length settings
|
||||
blocked:
|
||||
deny:
|
||||
- pkg: "github.com/pkg/errors"
|
||||
desc: Use fmt.Errorf with %w or errors stdlib instead.
|
||||
- pkg: "io/ioutil"
|
||||
desc: Deprecated since Go 1.16. Use io and os packages instead.
|
||||
- pkg: "github.com/instana/testify"
|
||||
desc: Use github.com/stretchr/testify instead.
|
||||
dupl:
|
||||
threshold: 100
|
||||
funlen:
|
||||
lines: 150 # Increased for existing code
|
||||
statements: 80 # Increased for existing code
|
||||
ignore-comments: true
|
||||
|
||||
# Code critic settings
|
||||
lines: -1
|
||||
statements: 50
|
||||
goconst:
|
||||
min-len: 2
|
||||
min-occurrences: 3
|
||||
gocritic:
|
||||
enabled-tags:
|
||||
- diagnostic
|
||||
- experimental
|
||||
- opinionated
|
||||
- performance
|
||||
- style
|
||||
disabled-checks:
|
||||
- hugeParam # Large value parameters (sometimes needed)
|
||||
- rangeValCopy # Range value copy (minimal performance impact)
|
||||
- commentedOutCode # Allow commented code for now
|
||||
- ifElseChain # Allow if-else chains
|
||||
settings:
|
||||
rangeExprCopy:
|
||||
sizeThreshold: 512
|
||||
|
||||
# Dependency guard settings
|
||||
depguard:
|
||||
rules:
|
||||
main:
|
||||
files:
|
||||
- $all
|
||||
deny:
|
||||
- pkg: "github.com/pkg/errors"
|
||||
desc: "Use standard library errors package instead"
|
||||
- pkg: "io/ioutil"
|
||||
desc: "io/ioutil is deprecated, use io or os package"
|
||||
|
||||
# Spell check settings
|
||||
- dupImport
|
||||
- hugeParam
|
||||
- rangeValCopy
|
||||
- ifElseChain
|
||||
- octalLiteral
|
||||
- whyNoLint
|
||||
- singleCaseSwitch
|
||||
- exitAfterDefer
|
||||
- commentedOutCode
|
||||
lll:
|
||||
line-length: 140
|
||||
gocognit:
|
||||
min-complexity: 30
|
||||
godox:
|
||||
keywords:
|
||||
- FIXME
|
||||
govet:
|
||||
enable:
|
||||
- nilness
|
||||
errorlint:
|
||||
asserts: false
|
||||
gosec:
|
||||
excludes:
|
||||
- G101
|
||||
- G104
|
||||
- G304
|
||||
- G401
|
||||
- G405
|
||||
- G501
|
||||
- G502
|
||||
- G505
|
||||
- G115
|
||||
- G117
|
||||
- G204
|
||||
errcheck:
|
||||
check-type-assertions: true
|
||||
exclude-functions:
|
||||
- "os.Remove"
|
||||
- "os.RemoveAll"
|
||||
- "(*database/sql.DB).Close"
|
||||
- "(*database/sql.Rows).Close"
|
||||
misspell:
|
||||
locale: US
|
||||
ignore-rules:
|
||||
- behaviour # British spelling
|
||||
revive:
|
||||
rules:
|
||||
- name: indent-error-flow
|
||||
- name: unexported-return
|
||||
disabled: true
|
||||
- name: unused-parameter
|
||||
disabled: true
|
||||
- name: package-comments
|
||||
disabled: true
|
||||
- name: exported
|
||||
disabled: true
|
||||
staticcheck:
|
||||
checks:
|
||||
- "all"
|
||||
- "-ST1000"
|
||||
- "-ST1003"
|
||||
- "-ST1016"
|
||||
- "-ST1020"
|
||||
- "-ST1021"
|
||||
- "-ST1022"
|
||||
|
||||
# goconst settings - make it less aggressive
|
||||
goconst:
|
||||
min-len: 5 # Minimum length of string constant
|
||||
min-occurrences: 5 # Increased from default 3
|
||||
exclusions:
|
||||
presets:
|
||||
- comments
|
||||
- std-error-handling
|
||||
- common-false-positives
|
||||
- legacy
|
||||
rules:
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- dupl
|
||||
- funlen
|
||||
- gosec
|
||||
- errcheck
|
||||
- testifylint
|
||||
- lll
|
||||
- source: "defer"
|
||||
linters:
|
||||
- errcheck
|
||||
- text: "SELECT"
|
||||
linters:
|
||||
- gosec
|
||||
# Temporary: known issues in pre-refactoring code (will be removed during refactoring)
|
||||
- text: "result 0 .* is always nil"
|
||||
linters:
|
||||
- unparam
|
||||
- text: "result 0 .* is never used"
|
||||
linters:
|
||||
- unparam
|
||||
- path: "browser/firefox/firefox.go"
|
||||
text: "field .* is unused"
|
||||
linters:
|
||||
- unused
|
||||
- path: "browserdata/sessionstorage/"
|
||||
text: "is unused"
|
||||
linters:
|
||||
- unused
|
||||
- path: "cmd/hack-browser-data/main.go"
|
||||
linters:
|
||||
- lll
|
||||
# Temporary: pre-refactoring code issues (all will be rewritten)
|
||||
- path: "browserdata/"
|
||||
linters:
|
||||
- dupl
|
||||
- gochecknoinits
|
||||
- goconst
|
||||
- lll
|
||||
- path: "browser/firefox/"
|
||||
linters:
|
||||
- gocritic
|
||||
- path: "crypto/"
|
||||
linters:
|
||||
- gocritic
|
||||
- path: "utils/chainbreaker/"
|
||||
linters:
|
||||
- gocritic
|
||||
- path: "browser/exploit/"
|
||||
linters:
|
||||
- gocritic
|
||||
- gocognit
|
||||
- funlen
|
||||
- whitespace
|
||||
- staticcheck
|
||||
|
||||
# Output configuration
|
||||
output:
|
||||
# Output format - use text format with colors
|
||||
formats:
|
||||
text:
|
||||
path: stdout
|
||||
colors: true
|
||||
formatters:
|
||||
enable:
|
||||
- gofumpt
|
||||
- goimports
|
||||
settings:
|
||||
gofumpt:
|
||||
extra-rules: true
|
||||
goimports:
|
||||
local-prefixes:
|
||||
- github.com/moond4rk/hackbrowserdata
|
||||
|
||||
@@ -2,263 +2,58 @@
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## ⚠️ CRITICAL SECURITY AND LEGAL NOTICE
|
||||
## Security Notice
|
||||
|
||||
**THIS PROJECT IS STRICTLY FOR SECURITY RESEARCH AND DEFENSIVE PURPOSES ONLY**
|
||||
|
||||
- This tool is ONLY intended for legitimate security research, authorized audits, and defensive security operations
|
||||
- ANY use of this project for unauthorized access, data theft, or malicious purposes is STRICTLY PROHIBITED and may violate computer fraud and abuse laws
|
||||
- Users are SOLELY responsible for ensuring compliance with all applicable laws and regulations in their jurisdiction
|
||||
- The original author and contributors assume NO legal responsibility for misuse of this tool
|
||||
- You MUST have explicit authorization before using this tool on any system you do not own
|
||||
- This tool should NEVER be used for attacking, credential harvesting, or any malicious intent
|
||||
- All security research must be conducted ethically and within legal boundaries
|
||||
This project is for security research and defensive purposes only. Do not generate code that could be used for unauthorized access. All security research must be conducted ethically and within legal boundaries.
|
||||
|
||||
## Project Overview
|
||||
|
||||
HackBrowserData is a command-line security research tool for extracting and decrypting browser data across multiple platforms (Windows, macOS, Linux). It supports data extraction from Chromium-based browsers (Chrome, Edge, Brave, etc.) and Firefox.
|
||||
HackBrowserData is a CLI security research tool for extracting and decrypting browser data across Windows, macOS, and Linux. It supports Chromium-based browsers and Firefox.
|
||||
|
||||
**Legitimate Use Cases**:
|
||||
- Personal data backup and recovery
|
||||
- Authorized enterprise security audits
|
||||
- Digital forensics investigations (with proper authorization)
|
||||
- Security vulnerability research and defense improvement
|
||||
- Understanding browser security mechanisms for defensive purposes
|
||||
**Constraint**: Must build with Go 1.20 (Windows 7 support). Do not use features from Go 1.21+ (e.g., `log/slog`, `slices`, `maps`, `cmp` packages).
|
||||
|
||||
## Development Commands
|
||||
|
||||
### Build the Project
|
||||
```bash
|
||||
# Build for current platform
|
||||
cd cmd/hack-browser-data
|
||||
go build
|
||||
# Build (use go@1.20 for module operations)
|
||||
go build ./cmd/hack-browser-data/
|
||||
|
||||
# Cross-compile for Windows from macOS/Linux
|
||||
GOOS=windows GOARCH=amd64 go build
|
||||
# Cross-compile
|
||||
GOOS=windows GOARCH=amd64 go build ./cmd/hack-browser-data/
|
||||
GOOS=linux GOARCH=amd64 go build ./cmd/hack-browser-data/
|
||||
|
||||
# Cross-compile for Linux from macOS/Windows
|
||||
GOOS=linux GOARCH=amd64 go build
|
||||
|
||||
# Cross-compile for macOS from Linux/Windows
|
||||
GOOS=darwin GOARCH=amd64 go build
|
||||
```
|
||||
|
||||
### Testing
|
||||
```bash
|
||||
# Run all tests
|
||||
go test -v ./...
|
||||
|
||||
# Run tests with coverage
|
||||
# Test
|
||||
go test ./...
|
||||
go test -v ./... -covermode=count -coverprofile=coverage.out
|
||||
|
||||
# Run specific package tests
|
||||
go test -v ./browser/chromium/...
|
||||
go test -v ./crypto/...
|
||||
```
|
||||
|
||||
### Code Quality
|
||||
```bash
|
||||
# Format check
|
||||
gofmt -d .
|
||||
|
||||
# Run linter (requires golangci-lint)
|
||||
# Lint (requires golangci-lint v2)
|
||||
golangci-lint run
|
||||
|
||||
# Check spelling
|
||||
# Format (gofumpt is stricter than gofmt)
|
||||
gofumpt -l -w .
|
||||
goimports -w -local github.com/moond4rk/hackbrowserdata .
|
||||
|
||||
# Spelling
|
||||
typos
|
||||
|
||||
# Tidy dependencies
|
||||
# Dependencies (MUST use go@1.20 to avoid bumping go directive)
|
||||
# export GOROOT=$(brew --prefix go@1.20)/libexec && export PATH=$GOROOT/bin:$PATH
|
||||
go mod tidy
|
||||
go mod verify
|
||||
```
|
||||
|
||||
## Architecture Overview
|
||||
## Code Conventions
|
||||
|
||||
### Core Components
|
||||
- **Platform code**: use build tags (`_darwin.go`, `_windows.go`, `_linux.go`)
|
||||
- **Error handling**: `fmt.Errorf("context: %w", err)` for wrapping, never `_ =` to ignore errors
|
||||
- **Logging**: `log.Debugf` for record-level issues, `log.Warnf` for user-visible warnings. Extract methods should return errors, not log them.
|
||||
- **Naming**: follow Go conventions — `Config` not `BrowserConfig`, `Extract` not `BrowsingData`
|
||||
- **Tests**: use `t.TempDir()` for filesystem tests, `go-sqlmock` for database tests
|
||||
- **Architecture**: see `rfcs/` for design documents
|
||||
|
||||
**Browser Abstraction Layer** (`browser/`)
|
||||
- Interface-based design allowing easy addition of new browsers
|
||||
- Platform-specific implementations using build tags (`_darwin.go`, `_windows.go`, `_linux.go`)
|
||||
- Automatic profile discovery and multi-profile support
|
||||
## Key Constraints
|
||||
|
||||
**Data Extraction Pipeline**
|
||||
1. **Profile Discovery**: `profile/finder.go` locates browser profiles
|
||||
2. **File Management**: `filemanager/` handles secure copying of browser files
|
||||
3. **Decryption**: `crypto/` provides platform-specific decryption
|
||||
- Windows: DPAPI via Windows API
|
||||
- macOS: Keychain access (requires user password)
|
||||
- Linux: PBKDF2 key derivation
|
||||
4. **Data Processing**: `browserdata/` parses and structures extracted data
|
||||
5. **Output**: `browserdata/outputter.go` exports to CSV/JSON
|
||||
|
||||
**Key Interfaces**
|
||||
- `Browser`: Main interface for browser implementations
|
||||
- `DataType`: Enum for different data types (passwords, cookies, etc.)
|
||||
- `BrowserData`: Container for all extracted browser data
|
||||
|
||||
### Platform-Specific Considerations
|
||||
|
||||
**macOS**
|
||||
- Requires user password for Keychain access to decrypt Chrome passwords
|
||||
- Uses Security framework for keychain operations
|
||||
- Profile paths: `~/Library/Application Support/[Browser]/`
|
||||
|
||||
**Windows**
|
||||
- Uses DPAPI for decryption (no password required)
|
||||
- Accesses Local State file for encryption keys
|
||||
- Profile paths: `%LOCALAPPDATA%/[Browser]/User Data/`
|
||||
|
||||
**Linux**
|
||||
- Uses PBKDF2 with "peanuts" as salt
|
||||
- Requires gnome-keyring or kwallet access
|
||||
- Profile paths: `~/.config/[Browser]/`
|
||||
|
||||
### Security Mechanisms
|
||||
|
||||
**Data Protection**
|
||||
- Temporary file cleanup after extraction
|
||||
- No persistent storage of decrypted master keys
|
||||
- Secure memory handling for sensitive data
|
||||
|
||||
**File Operations**
|
||||
- Copy-on-read to avoid modifying original browser files
|
||||
- Lock file filtering to prevent conflicts
|
||||
- Atomic operations where possible
|
||||
|
||||
## Adding New Browser Support
|
||||
|
||||
1. Create browser-specific package in `browser/[name]/`
|
||||
2. Implement the `Browser` interface
|
||||
3. Add platform-specific profile paths in `browser/consts.go`
|
||||
4. Register in `browser/browser.go` picker functions
|
||||
5. Add data type mappings in `types/types.go`
|
||||
|
||||
## Important Files and Their Roles
|
||||
|
||||
- `cmd/hack-browser-data/main.go`: CLI entry point and flag handling
|
||||
- `browser/chromium/chromium.go`: Core Chromium implementation
|
||||
- `crypto/crypto_[platform].go`: Platform-specific decryption
|
||||
- `extractor/extractor.go`: Main extraction orchestration
|
||||
- `profile/finder.go`: Browser profile discovery logic
|
||||
- `browserdata/password/password.go`: Password parsing and decryption
|
||||
|
||||
## Testing Considerations
|
||||
|
||||
- Tests use mocked data to avoid requiring actual browser installations
|
||||
- Platform-specific tests are isolated with build tags
|
||||
- Sensitive operations (like keychain access) are mocked in tests
|
||||
- Use `DATA-DOG/go-sqlmock` for database operation testing
|
||||
|
||||
## Browser Security Analysis
|
||||
|
||||
### Chromium-Based Browsers Security
|
||||
|
||||
**Encryption Methods**:
|
||||
- **Chrome v80+**: AES-256-GCM encryption for sensitive data
|
||||
- **Pre-v80**: AES-128-CBC with PKCS#5 padding
|
||||
- **Master Key Storage**:
|
||||
- Windows: Encrypted with DPAPI in `Local State` file
|
||||
- macOS: Stored in system Keychain (requires user password)
|
||||
- Linux: Derived using PBKDF2 with "peanuts" salt
|
||||
|
||||
**Data Protection Layers**:
|
||||
1. **Password Storage**: Encrypted in SQLite database (`Login Data`)
|
||||
2. **Cookie Encryption**: Encrypted values in `Cookies` database
|
||||
3. **Credit Card Data**: Encrypted with same master key as passwords
|
||||
4. **Local Storage**: Stored in LevelDB format, some values encrypted
|
||||
|
||||
### Firefox Security
|
||||
|
||||
**Encryption Architecture**:
|
||||
- **Master Password**: Optional user-defined password for additional protection
|
||||
- **Key Database**: `key4.db` stores encrypted master keys
|
||||
- **NSS Library**: Network Security Services for cryptographic operations
|
||||
- **Profile Encryption**: Each profile has independent encryption keys
|
||||
|
||||
**Key Derivation**:
|
||||
- Uses PKCS#5 PBKDF2 for key derivation
|
||||
- Triple-DES (3DES) for legacy compatibility
|
||||
- AES-256-CBC for modern encryption
|
||||
- ASN.1 encoding for key storage
|
||||
|
||||
### Platform-Specific Security Mechanisms
|
||||
|
||||
**Windows DPAPI (Data Protection API)**:
|
||||
- User-specific encryption tied to Windows login
|
||||
- No additional password required for decryption
|
||||
- Keys protected by Windows security subsystem
|
||||
- Vulnerable if attacker has user-level access
|
||||
|
||||
**macOS Keychain Services**:
|
||||
- Requires user password for access
|
||||
- Integration with system security framework
|
||||
- Protected by System Integrity Protection (SIP)
|
||||
- Security command-line tool for programmatic access
|
||||
|
||||
**Linux Secret Service**:
|
||||
- GNOME Keyring or KDE Wallet integration
|
||||
- D-Bus communication for key retrieval
|
||||
- User session-based protection
|
||||
- Fallback to PBKDF2 if keyring unavailable
|
||||
|
||||
### Security Vulnerabilities and Mitigations
|
||||
|
||||
**Known Attack Vectors**:
|
||||
1. **Physical Access**: Direct file system access to browser profiles
|
||||
2. **Memory Dumps**: Extraction of decrypted data from RAM
|
||||
3. **Malware**: Keyloggers and info-stealers targeting browsers
|
||||
4. **Process Injection**: DLL injection to extract decrypted data
|
||||
|
||||
**Defensive Recommendations**:
|
||||
1. **Enable Master Password**: Firefox users should set master password
|
||||
2. **Use OS-Level Encryption**: FileVault (macOS), BitLocker (Windows), LUKS (Linux)
|
||||
3. **Regular Updates**: Keep browsers updated for latest security patches
|
||||
4. **Profile Isolation**: Use separate profiles for sensitive activities
|
||||
5. **Hardware Keys**: Use FIDO2/WebAuthn for critical accounts
|
||||
|
||||
### Cryptographic Implementation Details
|
||||
|
||||
**AES-GCM (Galois/Counter Mode)**:
|
||||
- Authenticated encryption with associated data (AEAD)
|
||||
- 96-bit nonce/IV for randomization
|
||||
- 128-bit authentication tag for integrity
|
||||
- Used in Chrome v80+ for enhanced security
|
||||
|
||||
**PBKDF2 (Password-Based Key Derivation Function 2)**:
|
||||
- Iterations: 1003 (macOS), 1 (Linux default)
|
||||
- Hash function: SHA-1 (legacy) or SHA-256
|
||||
- Salt: "saltysalt" (Chrome), "peanuts" (Linux)
|
||||
- Output: 128-bit or 256-bit keys
|
||||
|
||||
**DPAPI Internals**:
|
||||
- Uses CryptProtectData/CryptUnprotectData Windows APIs
|
||||
- Machine-specific or user-specific encryption
|
||||
- Automatic key management by Windows
|
||||
- Integrates with Windows credential manager
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `modernc.org/sqlite`: Pure Go SQLite for cross-platform compatibility
|
||||
- `github.com/godbus/dbus`: Linux keyring access
|
||||
- `github.com/ppacher/go-dbus-keyring`: Secret service integration
|
||||
- `github.com/tidwall/gjson`: JSON parsing for browser preferences
|
||||
- `github.com/syndtr/goleveldb`: LevelDB for IndexedDB/LocalStorage
|
||||
|
||||
## Ethical Usage Guidelines
|
||||
|
||||
### Responsible Disclosure
|
||||
- Report vulnerabilities to browser vendors through official channels
|
||||
- Allow reasonable time for patches before public disclosure
|
||||
- Never exploit vulnerabilities for personal gain
|
||||
|
||||
### Legal Compliance
|
||||
- Obtain written authorization before testing third-party systems
|
||||
- Comply with GDPR, CCPA, and other privacy regulations
|
||||
- Respect intellectual property and terms of service
|
||||
- Maintain audit logs of all security testing activities
|
||||
|
||||
### Best Practices for Security Researchers
|
||||
1. **Scope Definition**: Clearly define testing boundaries
|
||||
2. **Data Handling**: Securely delete any extracted sensitive data
|
||||
3. **Documentation**: Maintain detailed records of methodologies
|
||||
4. **Collaboration**: Work with security community ethically
|
||||
5. **Education**: Share knowledge to improve overall security
|
||||
- `modernc.org/sqlite` pinned at v1.31.1 (v1.32+ requires Go 1.21)
|
||||
- `golang.org/x/text` will be removed in refactoring (use 3-byte UTF-8 BOM instead)
|
||||
- No `pkg/` + `internal/` directory structure — keep it simple
|
||||
- No root-level library API — CLI calls `browser.PickBrowsers()` directly
|
||||
|
||||
+2
-4
@@ -4,10 +4,8 @@ import (
|
||||
"github.com/moond4rk/hackbrowserdata/log/level"
|
||||
)
|
||||
|
||||
var (
|
||||
// defaultLogger is the default logger used by the package-level functions.
|
||||
defaultLogger = NewLogger(nil)
|
||||
)
|
||||
// defaultLogger is the default logger used by the package-level functions.
|
||||
var defaultLogger = NewLogger(nil)
|
||||
|
||||
func SetVerbose() {
|
||||
defaultLogger.SetLevel(level.DebugLevel)
|
||||
|
||||
+1
-1
@@ -136,7 +136,7 @@ func (l *baseLogger) prefixPrint(prefix string, args ...any) {
|
||||
}
|
||||
|
||||
func (l *baseLogger) getCallDepth() int {
|
||||
var defaultCallDepth = 2
|
||||
defaultCallDepth := 2
|
||||
pcs := make([]uintptr, 10)
|
||||
n := runtime.Callers(defaultCallDepth, pcs)
|
||||
frames := runtime.CallersFrames(pcs[:n])
|
||||
|
||||
+29
-33
@@ -22,20 +22,18 @@ type baseTestCase struct {
|
||||
wantedPattern string
|
||||
}
|
||||
|
||||
var (
|
||||
baseTestCases = []baseTestCase{
|
||||
{
|
||||
description: "without trailing newline, logger adds newline",
|
||||
message: "hello, hacker!",
|
||||
suffix: "",
|
||||
},
|
||||
{
|
||||
description: "with trailing newline, logger preserves newline",
|
||||
message: "hello, hacker!",
|
||||
suffix: "\n",
|
||||
},
|
||||
}
|
||||
)
|
||||
var baseTestCases = []baseTestCase{
|
||||
{
|
||||
description: "without trailing newline, logger adds newline",
|
||||
message: "hello, hacker!",
|
||||
suffix: "",
|
||||
},
|
||||
{
|
||||
description: "with trailing newline, logger preserves newline",
|
||||
message: "hello, hacker!",
|
||||
suffix: "\n",
|
||||
},
|
||||
}
|
||||
|
||||
func TestLoggerDebug(t *testing.T) {
|
||||
for _, tc := range baseTestCases {
|
||||
@@ -121,25 +119,23 @@ type formatTestCase struct {
|
||||
wantedPattern string
|
||||
}
|
||||
|
||||
var (
|
||||
formatTestCases = []formatTestCase{
|
||||
{
|
||||
description: "message with format prefix",
|
||||
format: "hello, %s!",
|
||||
args: []any{"Hacker"},
|
||||
},
|
||||
{
|
||||
description: "message with format prefix",
|
||||
format: "hello, %d,%d,%d!",
|
||||
args: []any{1, 2, 3},
|
||||
},
|
||||
{
|
||||
description: "message with format prefix",
|
||||
format: "hello, %s,%d,%d!",
|
||||
args: []any{"Hacker", 2, 3},
|
||||
},
|
||||
}
|
||||
)
|
||||
var formatTestCases = []formatTestCase{
|
||||
{
|
||||
description: "message with format prefix",
|
||||
format: "hello, %s!",
|
||||
args: []any{"Hacker"},
|
||||
},
|
||||
{
|
||||
description: "message with format prefix",
|
||||
format: "hello, %d,%d,%d!",
|
||||
args: []any{1, 2, 3},
|
||||
},
|
||||
{
|
||||
description: "message with format prefix",
|
||||
format: "hello, %s,%d,%d!",
|
||||
args: []any{"Hacker", 2, 3},
|
||||
},
|
||||
}
|
||||
|
||||
func TestLoggerDebugf(t *testing.T) {
|
||||
for _, tc := range formatTestCases {
|
||||
|
||||
+3
-2
@@ -3,6 +3,7 @@ package types
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
@@ -39,9 +40,9 @@ func TestDataType_TempFilename(t *testing.T) {
|
||||
|
||||
for _, tc := range testCases {
|
||||
expectedPrefix := tc.expected + "_" + strconv.Itoa(int(tc.item)) + ".temp"
|
||||
actualPath := tc.item.TempFilename()
|
||||
actualPath := filepath.ToSlash(tc.item.TempFilename())
|
||||
asserts.Contains(actualPath, expectedPrefix, "TempFilename should contain the correct prefix for "+tc.expected)
|
||||
asserts.Contains(actualPath, os.TempDir(), "TempFilename should be in the system temp directory for "+tc.expected)
|
||||
asserts.Contains(actualPath, filepath.ToSlash(os.TempDir()), "TempFilename should be in the system temp directory for "+tc.expected)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -425,7 +425,7 @@ func parseKeyBlob(buf []byte) (keyBlob, error) {
|
||||
return kb, nil
|
||||
}
|
||||
|
||||
func (kc *Keychain) getBaseAddress(tableID uint32, offset uint32) (int, error) {
|
||||
func (kc *Keychain) getBaseAddress(tableID, offset uint32) (int, error) {
|
||||
switch tableID {
|
||||
case 23972, 30912:
|
||||
tableID = 16
|
||||
|
||||
Reference in New Issue
Block a user