From 6a7e04de46b140b86c8ffb095f918b473a3f5ddf Mon Sep 17 00:00:00 2001 From: Ion Drimba Filho Date: Wed, 6 Aug 2025 11:49:48 -0300 Subject: [PATCH 01/11] wip --- src/app/index.js | 288 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100644 src/app/index.js diff --git a/src/app/index.js b/src/app/index.js new file mode 100644 index 0000000..c330c76 --- /dev/null +++ b/src/app/index.js @@ -0,0 +1,288 @@ +import React, { PureComponent, Suspense, lazy } from 'react'; +import { createBrowserHistory } from 'history' +import Home from '../pages/Home'; +import percent from '../helpers/percent'; +import Menu from '../components/Menu'; +import Page from '../components/Page'; +import Loader from '../components/Loader'; +import Audio from '../helpers/audio'; +import { initialState } from '../data'; +import './style.scss'; + +const List = lazy(() => import('../pages/List')); +const About = lazy(() => import('../pages/About')); +const Detail = lazy(() => import('../pages/Detail')); + +class App extends PureComponent { + constructor(props) { + super(props); + + this.playlistUrl = process.env.REACT_APP_API_URL; + this.state = { + ...initialState + }; + + this.history = createBrowserHistory(); + } + + componentDidMount() { + this.history.listen((history) => { + this.setState(() => { + return { currentView: history.location.state.view || '/' }; + }); + + if (history.location.state.view === 'list' && !this.state.tracks[0].id) { + this.fetchPlayList(); + }; + }); + + this.setupAudio(); + + this.history.push('/', { view: 'home' }); + } + + onStartClick = () => { + this.changeView('list'); + } + + fetchPlayList = async () => { + const result = await fetch(this.playlistUrl); + const tracks = await result.json(); + + this.updateSate(tracks); + } + + updateSate(tracks) { + const updatedState = { + tracks: [...tracks.map((track, index) => { + return Object.assign({}, { + ...this.state.track, + id: track.id, + stream_url: `${this.playlistUrl}/stream/${track.id}`, + uri: track.uri, + duration: track.duration, + favoritings_count: track.favoritings_count, + artist: track.user.username, + artwork_url: track.artwork_url ? track.artwork_url.replace('large', 't50x50') : '', + title: track.title.toLowerCase(), + permalink_url: track.permalink_url, + index, + }); + })], + playlistLoaded: true, + }; + + this.setState(() => updatedState); + } + + changeView(view) { + this.history.push(`/${view}`, { view }); + } + + setTrack(track) { + this.setState(() => { + return { + track, + currentTime: 0, + paused: true, + played: false, + playing: false, + changingTrack: true + }; + }); + } + + canChangeTrack() { + return this.state.changingTrack === false; + } + + getNextTrack() { + const nextTrack = this.state.tracks[this.state.track.index + 1]; + + return nextTrack ? { ...nextTrack } : null; + } + + getPreviousTrack() { + const prevTrack = this.state.tracks[this.state.track.index - 1]; + + return prevTrack ? { ...prevTrack } : null; + } + + changeTrack(track) { + this.audio.setAudioSource(''); + + if (this.canChangeTrack() && track) { + this.setTrack(track); + this.onPlayClick(track); + } + } + + selectTrack = (id) => { + return this.state.tracks.filter((track) => Number(id) === track.id)[0]; + } + + setupAudio() { + this.timeupdate = this.timeupdate.bind(this); + this.audioStop = this.audioStop.bind(this); + + this.audio = new Audio(document.querySelector('#audio'), this.props.audioContext); + this.audio.setup(); + this.audio.setTimerHandler(this.timeupdate); + this.audio.setStopHandler(this.audioStop); + this.audio.canplay(() => { + this.setState(() => { + return { + changingTrack: false + }; + }); + }) + } + + audioStop() { + this.setState({ + track: { + ...this.state.track, currentTime: 0, percentage: 0, playing: false, + played: false, + paused: true, + } + }); + } + + timeupdate = (evt) => { + this.setState({ + track: { + ...this.state.track, currentTime: evt.target.currentTime, + percentage: percent(evt.target.currentTime, evt.target.duration) / 100 + } + }); + } + + onListClick = (id) => { + if (id !== this.state.track.id) { + this.audio.setAudioSource(''); + } + + const track = { + ...this.selectTrack(id), + currentTime: 0, + percentage: 0, + playing: this.state.track.id === id ? this.state.track.playing : false, + played: this.state.track.id === id ? this.state.track.played : false, + paused: this.state.track.id === id ? this.state.track.paused : true, + }; + + this.setState(() => { + return { track }; + }); + + this.changeView('detail'); + + this.onPlayClick(track); + } + + onPlayClick = async (track) => { + if (!track.played) { + const result = await fetch(track.stream_url); + const urlstream = await result.json(); + + this.audio.setAudioSource(urlstream.http_mp3_128_url); + } + + this.setState(() => { + return { + track: { + ...track, + paused: false, + playing: true, + played: true + } + }; + }); + + this.audio.resume(); + this.audio.play(); + } + + onPauseClick = (track) => { + this.audio.pause(); + + this.setState(() => { + return { + track: { + ...track, + paused: true, + playing: false + } + } + }); + } + + onBackClick = () => { + this.history.go(-1); + + this.setState(() => { + return { currentView: this.history.location.state.view || '/' }; + }); + } + + onAboutClick = () => { + this.changeView('about'); + } + + onPlayNext = () => { + this.changeTrack(this.getNextTrack()); + } + + onPlayPrev = () => { + this.changeTrack(this.getPreviousTrack()); + } + + onRepeatClick = () => { + const repeat = !this.state.repeat; + + this.setState(() => { + return { repeat }; + }); + + this.audio.repeat(repeat); + } + + render() { + return ( +
+ +
+ +
+ + + + }> + + + + + + + + + + +
+
+
+ ); + } +} + +export default App; \ No newline at end of file From 405ae4ad4817ff551c8d9a2b505692059b37b50e Mon Sep 17 00:00:00 2001 From: Ion Drimba Filho Date: Wed, 6 Aug 2025 11:54:05 -0300 Subject: [PATCH 02/11] wip --- src/helpers/audio/index.js | 75 ++++++++++++++++++++++++++++++++++ src/pages/Detail/index.js | 83 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 src/helpers/audio/index.js create mode 100644 src/pages/Detail/index.js diff --git a/src/helpers/audio/index.js b/src/helpers/audio/index.js new file mode 100644 index 0000000..476dac7 --- /dev/null +++ b/src/helpers/audio/index.js @@ -0,0 +1,75 @@ +export default class Audio { + constructor(element, audioCtx) { + this.element = element; + this.context = audioCtx; + this.repeatPlayback = false; + this._ended = this._ended.bind(this); + this.stopHandler = () => {}; + } + + _createAnalyser() { + this.analyser = this.context.createAnalyser(); + } + + _createMediaElementSource() { + this.source = this.context.createMediaElementSource(this.element); + this.source.connect(this.analyser); + this.analyser.connect(this.context.destination); + } + + _ended() { + if(this.repeatPlayback) { + this.play(); + } else { + this.stopHandler(); + } + } + + _canplay() { + this.canplayCallback(); + } + + canplay(callback) { + this.canplayCallback = callback; + } + + setup() { + this._createAnalyser(); + this._createMediaElementSource(); + + this.element.addEventListener('canplay', this._canplay.bind(this)); + this.element.addEventListener('ended', this._ended); + } + + setTimerHandler(callback) { + this.element.addEventListener('timeupdate', callback); + } + + setStopHandler(callback) { + this.stopHandler = callback; + } + + setVolume(amount) { + this.element.volume = amount; + } + + setAudioSource(src) { + this.element.src = src; + } + + resume() { + this.context.resume(); + } + + play() { + this.element.play(); + } + + pause() { + this.element.pause(); + } + + repeat(value) { + this.repeatPlayback = value; + } +} \ No newline at end of file diff --git a/src/pages/Detail/index.js b/src/pages/Detail/index.js new file mode 100644 index 0000000..ada9a3a --- /dev/null +++ b/src/pages/Detail/index.js @@ -0,0 +1,83 @@ +import React, { PureComponent, Fragment } from 'react'; +import PropTypes from 'prop-types'; +import ProgressBar from '../../components/ProgressBar'; +import MediaButton from '../../components/MediaButton'; +import AlbumCover from '../../components/AlbumCover'; +import convertSecondsToMMss from '../../helpers/timer'; +import IconButton from '../../components/IconButton'; +import { ReactComponent as PlayButton } from '../../icons/play-arrow.svg'; +import { ReactComponent as PauseButton } from '../../icons/pause.svg'; +import { ReactComponent as RepeatButton } from '../../icons/repeat-arrows.svg'; +import { ReactComponent as LinkButton } from '../../icons/link.svg'; +import './style.scss'; + +class Detail extends PureComponent { + onPlayClick = () => { + this.props.onPlayClick(this.props.track); + } + + onPauseClick = () => { + this.props.onPauseClick(this.props.track); + } + + onLinkClick = () => { + window.open(this.props.track.permalink_url); + } + + render() { + return ( + +
+ +
+
+

{this.props.track.title}

+

{this.props.track.artist}

+
+ +
+ + +
+
+ } /> + + } /> + } /> + + } /> +
+
+
+
+ ); + } +} + +Detail.propTypes = { + track: PropTypes.shape({ + currentTime: PropTypes.number.isRequired, + duration: PropTypes.number, + playing: PropTypes.bool.isRequired, + paused: PropTypes.bool.isRequired, + id: PropTypes.number, + artwork_url: PropTypes.string.isRequired, + title: PropTypes.string, + artist: PropTypes.string, + permalink_url: PropTypes.string + }), + repeat: PropTypes.bool, + active: PropTypes.bool.isRequired, + onRepeatClick: PropTypes.func.isRequired, + onBackClick: PropTypes.func, + onPauseClick: PropTypes.func.isRequired, + onPlayClick: PropTypes.func.isRequired, + onPlayPrev: PropTypes.func.isRequired, + onPlayNext: PropTypes.func.isRequired, +} + +export default Detail; \ No newline at end of file From aa2bcea1435688b568091ce7e1bb45c2905fb470 Mon Sep 17 00:00:00 2001 From: Ion Drimba Filho Date: Wed, 6 Aug 2025 12:12:06 -0300 Subject: [PATCH 03/11] www --- src/app/semgrep.js | 217 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 src/app/semgrep.js diff --git a/src/app/semgrep.js b/src/app/semgrep.js new file mode 100644 index 0000000..c9b91f6 --- /dev/null +++ b/src/app/semgrep.js @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2014-2022 Bjoern Kimminich & the OWASP Juice Shop contributors. + * SPDX-License-Identifier: MIT + */ + +import { Request, Response, NextFunction } from 'express' +import { UserModel } from 'models/user' + +/* jslint node: true */ +const crypto = require('crypto') +const expressJwt = require('express-jwt') +const jwt = require('jsonwebtoken') +const jws = require('jws') +const sanitizeHtml = require('sanitize-html') +const sanitizeFilename = require('sanitize-filename') +const z85 = require('z85') +const utils = require('./utils') +const fs = require('fs') + +const publicKey = fs.readFileSync('encryptionkeys/jwt.pub', 'utf8') +module.exports.publicKey = publicKey +const privateKey = '-----BEGIN RSA PRIVATE KEY-----\r\nMIICXAIBAAKBgQDNwqLEe9wgTXCbC7+RPdDbBbeqjdbs4kOPOIGzqLpXvJXlxxW8iMz0EaM4BKUqYsIa+ndv3NAn2RxCd5ubVdJJcX43zO6Ko0TFEZx/65gY3BE0O6syCEmUP4qbSd6exou/F+WTISzbQ5FBVPVmhnYhG/kpwt/cIxK5iUn5hm+4tQIDAQABAoGBAI+8xiPoOrA+KMnG/T4jJsG6TsHQcDHvJi7o1IKC/hnIXha0atTX5AUkRRce95qSfvKFweXdJXSQ0JMGJyfuXgU6dI0TcseFRfewXAa/ssxAC+iUVR6KUMh1PE2wXLitfeI6JLvVtrBYswm2I7CtY0q8n5AGimHWVXJPLfGV7m0BAkEA+fqFt2LXbLtyg6wZyxMA/cnmt5Nt3U2dAu77MzFJvibANUNHE4HPLZxjGNXN+a6m0K6TD4kDdh5HfUYLWWRBYQJBANK3carmulBwqzcDBjsJ0YrIONBpCAsXxk8idXb8jL9aNIg15Wumm2enqqObahDHB5jnGOLmbasizvSVqypfM9UCQCQl8xIqy+YgURXzXCN+kwUgHinrutZms87Jyi+D8Br8NY0+Nlf+zHvXAomD2W5CsEK7C+8SLBr3k/TsnRWHJuECQHFE9RA2OP8WoaLPuGCyFXaxzICThSRZYluVnWkZtxsBhW2W8z1b8PvWUE7kMy7TnkzeJS2LSnaNHoyxi7IaPQUCQCwWU4U+v4lD7uYBw00Ga/xt+7+UqFPlPVdz1yyr4q24Zxaw0LgmuEvgU5dycq8N7JxjTubX0MIRR+G9fmDBBl8=\r\n-----END RSA PRIVATE KEY-----' + +interface ResponseWithUser { + status: string + data: UserModel + iat: number + exp: number + bid: number +} + +interface IAuthenticatedUsers { + tokenMap: { [key: string]: ResponseWithUser } + idMap: {[key: string]: string} + put: (token: string, user: ResponseWithUser) => void + get: (token: string) => ResponseWithUser | undefined + tokenOf: (user: UserModel) => string | undefined + from: (req: Request) => ResponseWithUser | undefined + updateFrom: (req: Request, user: ResponseWithUser) => any +} + +exports.hash = (data: string) => crypto.createHash('md5').update(data).digest('hex') +exports.hmac = (data: string) => crypto.createHmac('sha256', 'pa4qacea4VK9t9nGv7yZtwmj').update(data).digest('hex') + +exports.cutOffPoisonNullByte = (str: string) => { + const nullByte = '%00' + if (utils.contains(str, nullByte)) { + return str.substring(0, str.indexOf(nullByte)) + } + return str +} + +exports.isAuthorized = () => expressJwt({ secret: publicKey }) +exports.denyAll = () => expressJwt({ secret: '' + Math.random() }) +exports.authorize = (user = {}) => jwt.sign(user, privateKey, { expiresInMinutes: 60 * 5, algorithm: 'RS256' }) +const verify = (token: string) => jws.verify(token, publicKey) +module.exports.verify = verify +const decode = (token: string) => { return jws.decode(token).payload } +module.exports.decode = decode + +exports.sanitizeHtml = (html: string) => sanitizeHtml(html) +exports.sanitizeLegacy = (input = '') => input.replace(/<(?:\w+)\W+?[\w]/gi, '') +exports.sanitizeFilename = (filename: string) => sanitizeFilename(filename) +const sanitizeSecure = (html: string): string | null => { + const sanitized = sanitizeHtml(html) + if (sanitized === html) { + return html + } else { + return sanitizeSecure(sanitized) + } +} + +module.exports.sanitizeSecure = sanitizeSecure + +const authenticatedUsers: IAuthenticatedUsers = { + tokenMap: {}, + idMap: {}, + put: function (token: string, user: { + status: string + data: UserModel + iat: number + exp: number + bid: number + }) { + this.tokenMap[token] = user + this.idMap[user.data.id] = token + }, + get: function (token: string) { + return token ? this.tokenMap[utils.unquote(token)] : undefined + }, + tokenOf: function (user: UserModel) { + return user ? this.idMap[user.id] : undefined + }, + from: function (req: Request) { + const token = utils.jwtFrom(req) + return token ? this.get(token) : undefined + }, + updateFrom: function (req: Request, user: ResponseWithUser) { + const token = utils.jwtFrom(req) + this.put(token, user) + } +} + +module.exports.authenticatedUsers = authenticatedUsers + +exports.userEmailFrom = ({ headers }: any) => { + return headers ? headers['x-user-email'] : undefined +} + +exports.generateCoupon = (discount: number, date = new Date()) => { + const coupon = utils.toMMMYY(date) + '-' + discount + return z85.encode(coupon) +} + +exports.discountFromCoupon = (coupon: string) => { + if (coupon) { + const decoded = z85.decode(coupon) + if (decoded && hasValidFormat(decoded.toString())) { + const parts = decoded.toString().split('-') + const validity = parts[0] + if (utils.toMMMYY(new Date()) === validity) { + const discount = parts[1] + return parseInt(discount) + } + } + } + return undefined +} + +function hasValidFormat (coupon: string) { + return coupon.match(/(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)[0-9]{2}-[0-9]{2}/) +} + +// vuln-code-snippet start redirectCryptoCurrencyChallenge redirectChallenge +const redirectAllowlist = new Set([ + 'https://github.com/bkimminich/juice-shop', + 'https://blockchain.info/address/1AbKfgvw9psQ41NbLi8kufDQTezwG8DRZm', // vuln-code-snippet vuln-line redirectCryptoCurrencyChallenge + 'https://explorer.dash.org/address/Xr556RzuwX6hg5EGpkybbv5RanJoZN17kW', // vuln-code-snippet vuln-line redirectCryptoCurrencyChallenge + 'https://etherscan.io/address/0x0f933ab9fcaaa782d0279c300d73750e1311eae6', // vuln-code-snippet vuln-line redirectCryptoCurrencyChallenge + 'http://shop.spreadshirt.com/juiceshop', + 'http://shop.spreadshirt.de/juiceshop', + 'https://www.stickeryou.com/products/owasp-juice-shop/794', + 'http://leanpub.com/juice-shop' +]) +exports.redirectAllowlist = redirectAllowlist + +exports.isRedirectAllowed = (url: string) => { + let allowed = false + for (const allowedUrl of redirectAllowlist) { + allowed = allowed || url.includes(allowedUrl) // vuln-code-snippet vuln-line redirectChallenge + } + return allowed +} +// vuln-code-snippet end redirectCryptoCurrencyChallenge redirectChallenge + +const roles = { + customer: 'customer', + deluxe: 'deluxe', + accounting: 'accounting', + admin: 'admin' +} + +module.exports.roles = roles + +const deluxeToken = (email: string) => { + const hmac = crypto.createHmac('sha256', privateKey) + return hmac.update(email + roles.deluxe).digest('hex') +} + +module.exports.deluxeToken = deluxeToken + +exports.isAccounting = () => { + return (req: Request, res: Response, next: NextFunction) => { + const decodedToken = verify(utils.jwtFrom(req)) && decode(utils.jwtFrom(req)) + if (decodedToken?.data?.role === exports.roles.accounting) { + next() + } else { + res.status(403).json({ error: 'Malicious activity detected' }) + } + } +} + +exports.isDeluxe = (req: Request) => { + const decodedToken = verify(utils.jwtFrom(req)) && decode(utils.jwtFrom(req)) + return decodedToken?.data?.role === exports.roles.deluxe && decodedToken?.data?.deluxeToken && decodedToken?.data?.deluxeToken === deluxeToken(decodedToken?.data?.email) +} + +exports.isCustomer = (req: Request) => { + const decodedToken = verify(utils.jwtFrom(req)) && decode(utils.jwtFrom(req)) + return decodedToken?.data?.role === exports.roles.customer +} + +exports.appendUserId = () => { + return (req: Request, res: Response, next: NextFunction) => { + try { + req.body.UserId = authenticatedUsers.tokenMap[utils.jwtFrom(req)].data.id + next() + } catch (error: any) { + res.status(401).json({ status: 'error', message: error }) + } + } +} + +exports.updateAuthenticatedUsers = () => (req: Request, res: Response, next: NextFunction) => { + const token = req.cookies.token || utils.jwtFrom(req) + if (token) { + jwt.verify(token, publicKey, (err: Error | null, decoded: any) => { + if (err === null) { + if (authenticatedUsers.get(token) === undefined) { + authenticatedUsers.put(token, decoded) + res.cookie('token', token) + } + } + }) + } + next() +} \ No newline at end of file From 60ea13c79d9d59c3e53cb816831515d741d680bf Mon Sep 17 00:00:00 2001 From: Ion Drimba Filho Date: Wed, 6 Aug 2025 12:12:38 -0300 Subject: [PATCH 04/11] sdsad --- src/app/d1.js | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 src/app/d1.js diff --git a/src/app/d1.js b/src/app/d1.js new file mode 100644 index 0000000..83c2107 --- /dev/null +++ b/src/app/d1.js @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014-2022 Bjoern Kimminich & the OWASP Juice Shop contributors. + * SPDX-License-Identifier: MIT + */ + +import challengeUtils = require('../lib/challengeUtils') +import { Request, Response, NextFunction } from 'express' +import { Review } from '../data/types' + +const challenges = require('../data/datacache').challenges +const db = require('../data/mongodb') +const security = require('../lib/insecurity') + +module.exports = function productReviews () { + return (req: Request, res: Response, next: NextFunction) => { + const id = req.body.id + const user = security.authenticatedUsers.from(req) + db.reviews.findOne({ _id: id }).then((review: Review) => { + if (!review) { + res.status(404).json({ error: 'Not found' }) + } else { + const likedBy = review.likedBy + if (!likedBy.includes(user.data.email)) { + db.reviews.update( + { _id: id }, + { $inc: { likesCount: 1 } } + ).then( + () => { + // Artificial wait for timing attack challenge + setTimeout(function () { + db.reviews.findOne({ _id: id }).then((review: Review) => { + const likedBy = review.likedBy + likedBy.push(user.data.email) + let count = 0 + for (let i = 0; i < likedBy.length; i++) { + if (likedBy[i] === user.data.email) { + count++ + } + } + challengeUtils.solveIf(challenges.timingAttackChallenge, () => { return count > 2 }) + db.reviews.update( + { _id: id }, + { $set: { likedBy: likedBy } } + ).then( + (result: any) => { + res.json(result) + }, (err: unknown) => { + res.status(500).json(err) + }) + }, () => { + res.status(400).json({ error: 'Wrong Params' }) + }) + }, 150) + }, (err: unknown) => { + res.status(500).json(err) + }) + } else { + res.status(403).json({ error: 'Not allowed' }) + } + } + }, () => { + res.status(400).json({ error: 'Wrong Params' }) + }) + } +} \ No newline at end of file From 310fda36770cf4cd85cdfb25f17fa792a5fd5e57 Mon Sep 17 00:00:00 2001 From: Ion Drimba Filho Date: Wed, 6 Aug 2025 12:44:52 -0300 Subject: [PATCH 05/11] wip --- .github/workflows/semgrep.yml | 44 ++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index d5c37e4..6b28de4 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -1,26 +1,38 @@ +# Name of this GitHub Actions workflow. +name: Semgrep CE scan + on: - workflow_dispatch: {} + # Scan in PRs: pull_request: {} + # Scan on-demand through GitHub Actions interface: + workflow_dispatch: {} + # Scan mainline branches and report all findings: push: - branches: - - main - - master - paths: - - .github/workflows/semgrep.yml + branches: ["master", "!main"] + # Schedule the CI job (this method uses cron syntax): schedule: - # random HH:MM to avoid a load spike on GitHub Actions at 00:00 - - cron: 42 3 * * * -name: Semgrep + - cron: '20 17 * * *' # Sets Semgrep to scan every day at 17:20 UTC. + # It is recommended to change the schedule to a random time. + +permissions: + contents: read + jobs: semgrep: - name: semgrep/ci + # User definable name of this GitHub Actions job. + name: semgrep-oss/scan + # If you are self-hosting, change the following `runs-on` value: runs-on: ubuntu-latest - permissions: - contents: read - env: - SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} + container: + # A Docker image with Semgrep installed. Do not change this. image: semgrep/semgrep + + # Skip any PR created by dependabot to avoid permission issues: + if: (github.actor != 'dependabot[bot]') + steps: - - uses: actions/checkout@v4 - - run: semgrep ci + # Fetch project source with GitHub Actions Checkout. Use either v3 or v4. + - uses: actions/checkout@v4 + # Run the "semgrep scan" command on the command line of the docker image. + - run: semgrep scan --config auto \ No newline at end of file From e1bfb078082b9a1d334ec7786c9edac925146130 Mon Sep 17 00:00:00 2001 From: Ion Drimba Filho Date: Wed, 6 Aug 2025 14:00:58 -0300 Subject: [PATCH 06/11] wip --- .github/workflows/semgrep.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index 6b28de4..384cd2c 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -35,4 +35,4 @@ jobs: # Fetch project source with GitHub Actions Checkout. Use either v3 or v4. - uses: actions/checkout@v4 # Run the "semgrep scan" command on the command line of the docker image. - - run: semgrep scan --config auto \ No newline at end of file + - run: semgrep scan --config auto --error \ No newline at end of file From 76dea4e5b76564c0619e0a7b7e6fe49192b26e97 Mon Sep 17 00:00:00 2001 From: Ion Drimba Filho Date: Wed, 6 Aug 2025 17:32:47 -0300 Subject: [PATCH 07/11] Update semgrep.yml --- .github/workflows/semgrep.yml | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index 384cd2c..1d68522 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -19,20 +19,12 @@ permissions: jobs: semgrep: - # User definable name of this GitHub Actions job. name: semgrep-oss/scan - # If you are self-hosting, change the following `runs-on` value: runs-on: ubuntu-latest - - container: - # A Docker image with Semgrep installed. Do not change this. - image: semgrep/semgrep - - # Skip any PR created by dependabot to avoid permission issues: if: (github.actor != 'dependabot[bot]') - steps: - # Fetch project source with GitHub Actions Checkout. Use either v3 or v4. - uses: actions/checkout@v4 - # Run the "semgrep scan" command on the command line of the docker image. - - run: semgrep scan --config auto --error \ No newline at end of file + - name: Run Semgrep + run: | + export SEMGREP_BASELINE_REF="${{ github.base_ref }}" # For pull requests + semgrep ci --config auto --error From dfd316fbe432d0cf39eb5c8b928c04c1a4ab6c56 Mon Sep 17 00:00:00 2001 From: Ion Drimba Filho Date: Wed, 6 Aug 2025 17:35:09 -0300 Subject: [PATCH 08/11] Update semgrep.yml --- .github/workflows/semgrep.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index 1d68522..e8427ce 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -21,6 +21,9 @@ jobs: semgrep: name: semgrep-oss/scan runs-on: ubuntu-latest + container: + # A Docker image with Semgrep installed. Do not change this. + image: semgrep/semgrep if: (github.actor != 'dependabot[bot]') steps: - uses: actions/checkout@v4 From 90222119f1e9e2a38e476cc7bff6ed28905a4fdf Mon Sep 17 00:00:00 2001 From: Ion Drimba Filho Date: Wed, 6 Aug 2025 17:36:30 -0300 Subject: [PATCH 09/11] Update semgrep.yml --- .github/workflows/semgrep.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index e8427ce..ae703d8 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -30,4 +30,4 @@ jobs: - name: Run Semgrep run: | export SEMGREP_BASELINE_REF="${{ github.base_ref }}" # For pull requests - semgrep ci --config auto --error + semgrep ci From db65fecd423c561c057095bb14ebaa216fa8051f Mon Sep 17 00:00:00 2001 From: Ion Drimba Filho Date: Wed, 6 Aug 2025 17:52:40 -0300 Subject: [PATCH 10/11] Update semgrep.yml --- .github/workflows/semgrep.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index ae703d8..193be73 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -28,6 +28,4 @@ jobs: steps: - uses: actions/checkout@v4 - name: Run Semgrep - run: | - export SEMGREP_BASELINE_REF="${{ github.base_ref }}" # For pull requests - semgrep ci + - run: semgrep scan --config auto --error From a1160a4527ce7b4bd0e1cadb009dfb462f026cfc Mon Sep 17 00:00:00 2001 From: Ion Drimba Filho Date: Wed, 6 Aug 2025 17:53:47 -0300 Subject: [PATCH 11/11] Update semgrep.yml --- .github/workflows/semgrep.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index 193be73..beb54b2 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -9,10 +9,6 @@ on: # Scan mainline branches and report all findings: push: branches: ["master", "!main"] - # Schedule the CI job (this method uses cron syntax): - schedule: - - cron: '20 17 * * *' # Sets Semgrep to scan every day at 17:20 UTC. - # It is recommended to change the schedule to a random time. permissions: contents: read @@ -28,4 +24,4 @@ jobs: steps: - uses: actions/checkout@v4 - name: Run Semgrep - - run: semgrep scan --config auto --error + run: semgrep scan --config auto --error