Skip to content

Commit

Permalink
SHARD-56: add better security for limit/offset query params (#95)
Browse files Browse the repository at this point in the history
* add better security for limit/offset query params

* fix: prefix logs with method name
  • Loading branch information
PudgyPug authored and urnotsam committed Oct 30, 2024
1 parent dcd2e8a commit ffe8027
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 2 deletions.
7 changes: 5 additions & 2 deletions src/Data/AccountDataProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,11 @@ export const provideAccountDataRequest = async (
// AND accountId <= "${accountEnd}" AND accountId >= "${accountStart}"
// ORDER BY timestamp, accountId LIMIT ${maxRecords}`

const safeSkip = Number.isInteger(offset) ? offset : 0
const safeLimit = Number.isInteger(maxRecords) ? maxRecords : 100
const sqlPrefix = `SELECT * FROM accounts WHERE `
const queryString = `accountId BETWEEN ? AND ? AND timestamp BETWEEN ? AND ? ORDER BY timestamp ASC, accountId ASC LIMIT ${maxRecords}`
const offsetCondition = ` OFFSET ${offset}`
const queryString = `accountId BETWEEN ? AND ? AND timestamp BETWEEN ? AND ? ORDER BY timestamp ASC, accountId ASC LIMIT ${safeLimit}`
const offsetCondition = ` OFFSET ${safeSkip}`
let sql = sqlPrefix
let values = []
if (accountOffset) {
Expand Down Expand Up @@ -263,6 +265,7 @@ export const provideAccountDataByListRequest = async (
): Promise<WrappedStateArray> => {
const { accountIds } = payload
const wrappedAccounts: WrappedStateArray = []
// todo: does this even work right now?
const sql = `SELECT * FROM accounts WHERE accountId IN (?)`
const accounts = await Account.fetchAccountsBySqlQuery(sql, accountIds)
for (const account of accounts) {
Expand Down
12 changes: 12 additions & 0 deletions src/dbstore/accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ export async function queryAccountByAccountId(accountId: string): Promise<Accoun
}

export async function queryLatestAccounts(count: number): Promise<AccountsCopy[] | null> {
if (!Number.isInteger(count)) {
Logger.mainLogger.error('queryLatestAccounts - Invalid count value')
return null
}
try {
const sql = `SELECT * FROM accounts ORDER BY cycleNumber DESC, timestamp DESC LIMIT ${
count ? count : 100
Expand All @@ -114,6 +118,10 @@ export async function queryLatestAccounts(count: number): Promise<AccountsCopy[]
export async function queryAccounts(skip = 0, limit = 10000): Promise<AccountsCopy[]> {
let dbAccounts: DbAccountCopy[]
const accounts: AccountsCopy[] = []
if (!Number.isInteger(skip) || !Number.isInteger(limit)) {
Logger.mainLogger.error('queryAccounts - Invalid skip or limit value')
return accounts
}
try {
const sql = `SELECT * FROM accounts ORDER BY cycleNumber ASC, timestamp ASC LIMIT ${limit} OFFSET ${skip}`
dbAccounts = (await db.all(accountDatabase, sql)) as DbAccountCopy[]
Expand Down Expand Up @@ -174,6 +182,10 @@ export async function queryAccountsBetweenCycles(
): Promise<AccountsCopy[]> {
let dbAccounts: DbAccountCopy[]
const accounts: AccountsCopy[] = []
if (!Number.isInteger(skip) || !Number.isInteger(limit)) {
Logger.mainLogger.error('queryAccountsBetweenCycles - Invalid skip or limit value')
return accounts
}
try {
const sql = `SELECT * FROM accounts WHERE cycleNumber BETWEEN ? AND ? ORDER BY cycleNumber ASC, timestamp ASC LIMIT ${limit} OFFSET ${skip}`
dbAccounts = (await db.all(accountDatabase, sql, [startCycleNumber, endCycleNumber])) as DbAccountCopy[]
Expand Down
4 changes: 4 additions & 0 deletions src/dbstore/cycles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ export async function queryCycleByMarker(marker: string): Promise<Cycle> {
}

export async function queryLatestCycleRecords(count: number): Promise<P2P.CycleCreatorTypes.CycleData[]> {
if (!Number.isInteger(count)) {
Logger.mainLogger.error('queryLatestCycleRecords - Invalid count value')
return []
}
try {
const sql = `SELECT * FROM cycles ORDER BY counter DESC LIMIT ${count ? count : 100}`
const dbCycles = (await db.all(cycleDatabase, sql)) as DbCycle[]
Expand Down
8 changes: 8 additions & 0 deletions src/dbstore/originalTxsData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ export async function queryOriginalTxsData(
endCycle?: number
): Promise<OriginalTxData[]> {
let originalTxsData: DbOriginalTxData[] = []
if (!Number.isInteger(skip) || !Number.isInteger(limit)) {
Logger.mainLogger.error('queryOriginalTxsData - Invalid skip or limit')
return originalTxsData
}
try {
let sql = `SELECT * FROM originalTxsData`
const sqlSuffix = ` ORDER BY cycle ASC, timestamp ASC LIMIT ${limit} OFFSET ${skip}`
Expand Down Expand Up @@ -166,6 +170,10 @@ export async function queryOriginalTxDataCountByCycles(
}

export async function queryLatestOriginalTxs(count: number): Promise<OriginalTxData[]> {
if (!Number.isInteger(count)) {
Logger.mainLogger.error('queryLatestOriginalTxs - Invalid count value')
return null
}
try {
const sql = `SELECT * FROM originalTxsData ORDER BY cycle DESC, timestamp DESC LIMIT ${
count ? count : 100
Expand Down
12 changes: 12 additions & 0 deletions src/dbstore/receipts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ export async function queryReceiptByReceiptId(receiptId: string, timestamp = 0):
}

export async function queryLatestReceipts(count: number): Promise<Receipt[]> {
if (!Number.isInteger(count)) {
Logger.mainLogger.error('queryLatestReceipts - Invalid count value')
return null
}
try {
const sql = `SELECT * FROM receipts ORDER BY cycle DESC, timestamp DESC LIMIT ${count ? count : 100}`
const receipts = (await db.all(receiptDatabase, sql)) as DbReceipt[]
Expand All @@ -179,6 +183,10 @@ export async function queryLatestReceipts(count: number): Promise<Receipt[]> {

export async function queryReceipts(skip = 0, limit = 10000): Promise<Receipt[]> {
let receipts: Receipt[] = []
if (!Number.isInteger(skip) || !Number.isInteger(limit)) {
Logger.mainLogger.error('queryReceipts - Invalid skip or limit')
return receipts
}
try {
const sql = `SELECT * FROM receipts ORDER BY cycle ASC, timestamp ASC LIMIT ${limit} OFFSET ${skip}`
receipts = (await db.all(receiptDatabase, sql)) as DbReceipt[]
Expand Down Expand Up @@ -261,6 +269,10 @@ export async function queryReceiptsBetweenCycles(
endCycleNumber: number
): Promise<Receipt[]> {
let receipts: Receipt[] = []
if (!Number.isInteger(skip) || !Number.isInteger(limit)) {
Logger.mainLogger.error('queryReceiptsBetweenCycles - Invalid skip or limit')
return receipts
}
try {
const sql = `SELECT * FROM receipts WHERE cycle BETWEEN ? AND ? ORDER BY cycle ASC, timestamp ASC LIMIT ${limit} OFFSET ${skip}`
receipts = (await db.all(receiptDatabase, sql, [startCycleNumber, endCycleNumber])) as DbReceipt[]
Expand Down
12 changes: 12 additions & 0 deletions src/dbstore/transactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ export async function queryTransactionByAccountId(accountId: string): Promise<Tr
}

export async function queryLatestTransactions(count: number): Promise<Transaction[]> {
if (!Number.isInteger(count)) {
Logger.mainLogger.error('queryLatestTransactions - Invalid count value')
return null
}
try {
const sql = `SELECT * FROM transactions ORDER BY cycleNumber DESC, timestamp DESC LIMIT ${
count ? count : 100
Expand All @@ -123,6 +127,10 @@ export async function queryLatestTransactions(count: number): Promise<Transactio

export async function queryTransactions(skip = 0, limit = 10000): Promise<Transaction[]> {
let transactions
if (!Number.isInteger(skip) || !Number.isInteger(limit)) {
Logger.mainLogger.error('queryTransactions - Invalid skip or limit')
return null
}
try {
const sql = `SELECT * FROM transactions ORDER BY cycleNumber ASC, timestamp ASC LIMIT ${limit} OFFSET ${skip}`
transactions = (await db.all(transactionDatabase, sql)) as DbTransaction[] // TODO: confirm structure of object from db
Expand Down Expand Up @@ -189,6 +197,10 @@ export async function queryTransactionsBetweenCycles(
endCycleNumber: number
): Promise<Transaction[]> {
let transactions
if (!Number.isInteger(skip) || !Number.isInteger(limit)) {
Logger.mainLogger.error('queryTransactionsBetweenCycles - Invalid skip or limit value')
return null
}
try {
const sql = `SELECT * FROM transactions WHERE cycleNumber BETWEEN ? AND ? ORDER BY cycleNumber ASC, timestamp ASC LIMIT ${limit} OFFSET ${skip}`
transactions = (await db.all(transactionDatabase, sql, [
Expand Down

0 comments on commit ffe8027

Please sign in to comment.